update jdt.core to I20220328-1800 (incl. Java 18 support)
diff --git a/features/org.eclipse.objectteams.otdt.core.patch/feature.xml b/features/org.eclipse.objectteams.otdt.core.patch/feature.xml
index 7cb190a..6e618b1 100644
--- a/features/org.eclipse.objectteams.otdt.core.patch/feature.xml
+++ b/features/org.eclipse.objectteams.otdt.core.patch/feature.xml
@@ -66,7 +66,7 @@
          id="org.eclipse.jdt.core"
          download-size="5614"
          install-size="5614"
-         version="3.29.0.OTDT_r282_qualifier"
+         version="3.30.0.OTDT_r282_qualifier"
          unpack="false"/>
 
 </feature>
diff --git a/org.eclipse.jdt.core.tests.compiler/META-INF/MANIFEST.MF b/org.eclipse.jdt.core.tests.compiler/META-INF/MANIFEST.MF
index 3f750af..611c6b4 100644
--- a/org.eclipse.jdt.core.tests.compiler/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.core.tests.compiler/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.jdt.core.tests.compiler;singleton:=true
-Bundle-Version: 3.12.1800.qualifier
+Bundle-Version: 3.12.1900.qualifier
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
 Export-Package: org.eclipse.jdt.core.tests.compiler,
diff --git a/org.eclipse.jdt.core.tests.compiler/pom.xml b/org.eclipse.jdt.core.tests.compiler/pom.xml
index 4387862..828c9af 100644
--- a/org.eclipse.jdt.core.tests.compiler/pom.xml
+++ b/org.eclipse.jdt.core.tests.compiler/pom.xml
@@ -15,11 +15,11 @@
   <parent>
     <artifactId>tests-pom</artifactId>
     <groupId>org.eclipse.jdt</groupId>
-    <version>4.23.0-SNAPSHOT</version>
+    <version>4.24.0-SNAPSHOT</version>
     <relativePath>../tests-pom/</relativePath>
   </parent>
   <artifactId>org.eclipse.jdt.core.tests.compiler</artifactId>
-  <version>3.12.1800-SNAPSHOT</version>
+  <version>3.12.1900-SNAPSHOT</version>
   <packaging>eclipse-test-plugin</packaging>
 
   <properties>
@@ -255,6 +255,36 @@
 			<tycho.surefire.argLine>--add-modules ALL-SYSTEM -Dcompliance=1.4,1.7,1.8,14,17</tycho.surefire.argLine>
 		</properties>
 	</profile>
+	<profile>
+		<id>test-on-javase-18</id>
+		<build>
+			<plugins>
+				<plugin>
+					<groupId>org.apache.maven.plugins</groupId>
+					<artifactId>maven-toolchains-plugin</artifactId>
+					<version>1.1</version>
+					<executions>
+						<execution>
+							<phase>validate</phase>
+							<goals>
+								<goal>toolchain</goal>
+							</goals>
+						</execution>
+					</executions>
+					<configuration>
+						<toolchains>
+							<jdk>
+								<id>JavaSE-18</id>
+							</jdk>
+						</toolchains>
+					</configuration>
+				</plugin>
+			</plugins>
+		</build>
+		<properties>
+			<tycho.surefire.argLine>--add-modules ALL-SYSTEM -Dcompliance=1.4,1.7,1.8,15,18</tycho.surefire.argLine>
+		</properties>
+	</profile>
   </profiles>
 
 </project>
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/JavadocCompletionParserTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/JavadocCompletionParserTest.java
index e035514..50a0bf3 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/JavadocCompletionParserTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/JavadocCompletionParserTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2019 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -239,11 +239,17 @@
 			TAG_INHERITDOC, TAG_LINKPLAIN, TAG_VALUE,
 			TAG_CODE, TAG_LITERAL, TAG_INDEX, TAG_SUMMARY
 		};
-	} else if(this.complianceLevel >= ClassFileConstants.JDK12) {
+	} else if(this.complianceLevel >= ClassFileConstants.JDK12
+			&& this.complianceLevel < ClassFileConstants.JDK18) {
 		additionalTags = new char[][] {
 			TAG_INHERITDOC, TAG_LINKPLAIN, TAG_VALUE,
 			TAG_CODE, TAG_LITERAL, TAG_INDEX, TAG_SUMMARY, TAG_SYSTEM_PROPERTY
 		};
+	} else if(this.complianceLevel >= ClassFileConstants.JDK18) {
+		additionalTags = new char[][] {
+			TAG_INHERITDOC, TAG_LINKPLAIN, TAG_VALUE,
+			TAG_CODE, TAG_LITERAL, TAG_INDEX, TAG_SUMMARY, TAG_SYSTEM_PROPERTY, TAG_SNIPPET
+		};
 	}
 	allTagsFinal = this.complianceLevel > ClassFileConstants.JDK1_8 ? allTagsJava9Plus  :  this.complianceLevel == ClassFileConstants.JDK1_8 ? allTagsJava8 : allTags  ;
 	if (additionalTags != null) {
@@ -354,11 +360,17 @@
 			TAG_CODE, TAG_LITERAL,
 			TAG_INDEX, TAG_SUMMARY
 		};
-	} else if(this.complianceLevel >= ClassFileConstants.JDK12) {
+	} else if(this.complianceLevel >= ClassFileConstants.JDK12
+			&& this.complianceLevel < ClassFileConstants.JDK18) {
 		additionalTags = new char[][] {
 			TAG_INHERITDOC, TAG_LINKPLAIN, TAG_VALUE,
 			TAG_CODE, TAG_LITERAL, TAG_INDEX, TAG_SUMMARY, TAG_SYSTEM_PROPERTY
 		};
+	} else if(this.complianceLevel >= ClassFileConstants.JDK18) {
+		additionalTags = new char[][] {
+			TAG_INHERITDOC, TAG_LINKPLAIN, TAG_VALUE,
+			TAG_CODE, TAG_LITERAL, TAG_INDEX, TAG_SUMMARY, TAG_SYSTEM_PROPERTY, TAG_SNIPPET
+		};
 	}
 	if (additionalTags != null) {
 		int length = allTags.length;
@@ -505,10 +517,15 @@
 		expectedTags = new char[][] {
 			TAG_SEE, TAG_SINCE, TAG_SERIAL, TAG_SERIAL_DATA, TAG_SERIAL_FIELD, TAG_SUMMARY
 		};
-	} else if (this.complianceLevel >= ClassFileConstants.JDK12) {
+	} else if (this.complianceLevel >= ClassFileConstants.JDK12
+			&& this.complianceLevel < ClassFileConstants.JDK18) {
 		expectedTags = new char[][] {
 			TAG_SEE, TAG_SINCE, TAG_SERIAL, TAG_SERIAL_DATA, TAG_SERIAL_FIELD, TAG_SUMMARY, TAG_SYSTEM_PROPERTY
 		};
+	} else if (this.complianceLevel >= ClassFileConstants.JDK18) {
+		expectedTags = new char[][] {
+			TAG_SEE, TAG_SINCE, TAG_SERIAL, TAG_SERIAL_DATA, TAG_SERIAL_FIELD, TAG_SUMMARY, TAG_SYSTEM_PROPERTY, TAG_SNIPPET
+		};
 	}
 	verifyCompletionOnJavadocTag("s".toCharArray(), expectedTags, false);
 	CompletionOnJavadocTag completionTag = (CompletionOnJavadocTag) this.javadoc.getCompletionNode();
@@ -607,12 +624,19 @@
 			TAG_CODE, TAG_LITERAL,
 			TAG_INDEX, TAG_SUMMARY
 		};
-	} else if (this.complianceLevel >= ClassFileConstants.JDK12) {
+	} else if(this.complianceLevel >= ClassFileConstants.JDK12
+			&& this.complianceLevel < ClassFileConstants.JDK18) {
 		additionalTags = new char[][] {
 			TAG_INHERITDOC, TAG_LINKPLAIN, TAG_VALUE,
 			TAG_CODE, TAG_LITERAL,
 			TAG_INDEX, TAG_SUMMARY, TAG_SYSTEM_PROPERTY
 		};
+	} else if (this.complianceLevel >= ClassFileConstants.JDK18) {
+		additionalTags = new char[][] {
+			TAG_INHERITDOC, TAG_LINKPLAIN, TAG_VALUE,
+			TAG_CODE, TAG_LITERAL,
+			TAG_INDEX, TAG_SUMMARY, TAG_SYSTEM_PROPERTY, TAG_SNIPPET
+		};
 	}
 	if (additionalTags != null) {
 		int length = allTags.length;
@@ -700,12 +724,20 @@
 			TAG_CODE, TAG_LITERAL,
 			TAG_INDEX, TAG_SUMMARY
 		};
-	} else if(this.complianceLevel >= ClassFileConstants.JDK12) {
+	} else if(this.complianceLevel >= ClassFileConstants.JDK12
+			&& this.complianceLevel < ClassFileConstants.JDK18) {
 		additionalTags = new char[][] {
 			TAG_INHERITDOC, TAG_LINKPLAIN, TAG_VALUE,
 			TAG_CODE, TAG_LITERAL,
 			TAG_INDEX, TAG_SUMMARY, TAG_SYSTEM_PROPERTY
 		};
+	} else if(this.complianceLevel >= ClassFileConstants.JDK18) {
+		additionalTags = new char[][] {
+			TAG_INHERITDOC, TAG_LINKPLAIN, TAG_VALUE,
+			TAG_CODE, TAG_LITERAL,
+			TAG_INDEX, TAG_SUMMARY, TAG_SYSTEM_PROPERTY,
+			TAG_SNIPPET
+		};
 	}
 	if (additionalTags != null) {
 		int length = allTags.length;
@@ -795,4 +827,101 @@
 	assertEquals("Invalid tag end position", end, completionTag.tagSourceEnd);
 }
 
+public void test033() {
+	String source = "package javadoc;\n" +
+		"/**\n" +
+		" * {@s+\n" +
+		" */\n" +
+		"public class Test {}\n";
+	verifyCompletionInJavadoc(source, "@s");
+
+	char[][] allTags = this.complianceLevel == ClassFileConstants.JDK1_3
+			? null : (this.complianceLevel < ClassFileConstants.JDK10
+			? null : (this.complianceLevel < ClassFileConstants.JDK12 ? new char[][] { TAG_SUMMARY }
+			: (this.complianceLevel < ClassFileConstants.JDK18 ? new char[][] { TAG_SUMMARY , TAG_SYSTEM_PROPERTY }
+			: new char[][] { TAG_SUMMARY,  TAG_SYSTEM_PROPERTY, TAG_SNIPPET  })));
+	verifyCompletionOnJavadocTag("s".toCharArray(), allTags, false);
+	CompletionOnJavadocTag completionTag = (CompletionOnJavadocTag) this.javadoc.getCompletionNode();
+	int start = source.indexOf("{@");
+	assertEquals("Invalid tag start position", start, completionTag.tagSourceStart);
+	int end = source.indexOf('+');
+	assertEquals("Invalid tag end position", end, completionTag.tagSourceEnd);
+}
+public void test034() {
+	if(this.complianceLevel < ClassFileConstants.JDK18)
+		return;
+	String source = "package javadoc;\n" +
+		"/**\n" +
+		" * {@snippet :+\n" +
+		" * class HelloWorld {+\n" +
+		" *      public static void main(String... args) {+\n" +
+		" *         System.out.println(\"Hello World!\");      // @highligh substring=\"println\"\n" +
+		" * }+\n" +
+		" * }+\n" +
+		" */\n" +
+		"public class Test {}\n";
+	verifyCompletionInJavadoc(source, "@highligh");
+
+	char[][] allTags =  new char[][] { TAG_HIGHLIGHT  };
+	verifyCompletionOnJavadocTag("highligh".toCharArray(), allTags, false);
+
+}
+public void test035() {
+	if(this.complianceLevel < ClassFileConstants.JDK18)
+		return;
+	String source = "package javadoc;\n" +
+		"/**\n" +
+		" * {@snippet :+\n" +
+		" * class HelloWorld {+\n" +
+		" *      public static void main(String... args) {+\n" +
+		" *         System.out.println(\"Hello World!\");      // @rep substring=\"println\"\n" +
+		" * }+\n" +
+		" * }+\n" +
+		" */\n" +
+		"public class Test {}\n";
+	verifyCompletionInJavadoc(source, "@rep");
+
+	char[][] allTags =  new char[][] { TAG_REPLACE };
+	verifyCompletionOnJavadocTag("rep".toCharArray(), allTags, false);
+
+}
+public void test036() {
+	if(this.complianceLevel < ClassFileConstants.JDK18)
+		return;
+	String source = "package javadoc;\n" +
+		"/**\n" +
+		" * {@snippet :+\n" +
+		" * class HelloWorld {+\n" +
+		" *      public static void main(String... args) {+\n" +
+		" *         System.out.println(\"Hello World!\");      // @dep substring=\"println\"\n" +
+		" * }+\n" +
+		" * }+\n" +
+		" */\n" +
+		"public class Test {}\n";
+	verifyCompletionInJavadoc(source, "@dep");
+
+	char[][] allTags =  null;// @deprecated should not be shown since in snippet
+	verifyCompletionOnJavadocTag("dep".toCharArray(), allTags, false);
+
+}
+public void test037() {
+	if(this.complianceLevel < ClassFileConstants.JDK18)
+		return;
+	String source = "package javadoc;\n" +
+		"/**\n" +
+		" * {@snippet :+\n" +
+		" * class HelloWorld {+\n" +
+		" *      public static void main(String... args) {+\n" +
+		" *         System.out.println(\"Hello World!\");      // @lin substring=\"println\"\n" +
+		" * }+\n" +
+		" * }+\n" +
+		" */\n" +
+		"public class Test {}\n";
+	verifyCompletionInJavadoc(source, "@lin");
+
+	char[][] allTags =  new char[][] { TAG_LINK };
+	verifyCompletionOnJavadocTag("lin".toCharArray(), allTags, false);
+
+}
+
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/TestAll.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/TestAll.java
index 84a0b6a..344628b 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/TestAll.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/TestAll.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2021 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -115,26 +115,14 @@
 	if ((possibleComplianceLevels & AbstractCompilerTest.F_1_8) != 0) {
 		ArrayList tests_1_8 = (ArrayList)testClasses.clone();
 		tests_1_8.addAll(TEST_CLASSES_1_5);
-		tests_1_8.add(ParserTest1_7.class);
-		tests_1_8.add(LambdaExpressionSyntaxTest.class);
-		tests_1_8.add(ReferenceExpressionSyntaxTest.class);
-		tests_1_8.add(TypeAnnotationSyntaxTest.class);
-		tests_1_8.add(CompletionParserTest18.class);
-		tests_1_8.add(SelectionParserTest18.class);
+		addJava1_8Tests(tests_1_8);
 		TestCase.resetForgottenFilters(tests_1_8);
 		all.addTest(AbstractCompilerTest.buildComplianceTestSuite(ClassFileConstants.JDK1_8, tests_1_8));
 	}
 	if ((possibleComplianceLevels & AbstractCompilerTest.F_9) != 0) {
 		ArrayList tests_9 = (ArrayList)testClasses.clone();
 		tests_9.addAll(TEST_CLASSES_1_5);
-		tests_9.add(ParserTest1_7.class);
-		tests_9.add(LambdaExpressionSyntaxTest.class);
-		tests_9.add(ReferenceExpressionSyntaxTest.class);
-		tests_9.add(TypeAnnotationSyntaxTest.class);
-		tests_9.add(CompletionParserTest18.class);
-		tests_9.add(SelectionParserTest18.class);
-		tests_9.add(SelectionParserTest9.class);
-		tests_9.add(ModuleDeclarationSyntaxTest.class);
+		addJava9Tests(tests_9);
 		// Reset forgotten subsets tests
 		TestCase.TESTS_PREFIX = null;
 		TestCase.TESTS_NAMES = null;
@@ -146,16 +134,7 @@
 	if ((possibleComplianceLevels & AbstractCompilerTest.F_10) != 0) {
 		ArrayList tests_10 = (ArrayList)testClasses.clone();
 		tests_10.addAll(TEST_CLASSES_1_5);
-		tests_10.add(ParserTest1_7.class);
-		tests_10.add(LambdaExpressionSyntaxTest.class);
-		tests_10.add(ReferenceExpressionSyntaxTest.class);
-		tests_10.add(TypeAnnotationSyntaxTest.class);
-		tests_10.add(CompletionParserTest18.class);
-		tests_10.add(SelectionParserTest18.class);
-		tests_10.add(SelectionParserTest9.class);
-		tests_10.add(SelectionParserTest10.class);
-		tests_10.add(ModuleDeclarationSyntaxTest.class);
-		tests_10.add(JEP286ReservedWordTest.class);
+		addJava10Tests(tests_10);
 		// Reset forgotten subsets tests
 		TestCase.TESTS_PREFIX = null;
 		TestCase.TESTS_NAMES = null;
@@ -167,16 +146,7 @@
 	if ((possibleComplianceLevels & AbstractCompilerTest.F_11) != 0) {
 		ArrayList tests_11 = (ArrayList)testClasses.clone();
 		tests_11.addAll(TEST_CLASSES_1_5);
-		tests_11.add(ParserTest1_7.class);
-		tests_11.add(LambdaExpressionSyntaxTest.class);
-		tests_11.add(ReferenceExpressionSyntaxTest.class);
-		tests_11.add(TypeAnnotationSyntaxTest.class);
-		tests_11.add(CompletionParserTest18.class);
-		tests_11.add(SelectionParserTest18.class);
-		tests_11.add(SelectionParserTest9.class);
-		tests_11.add(SelectionParserTest10.class);
-		tests_11.add(ModuleDeclarationSyntaxTest.class);
-		tests_11.add(JEP286ReservedWordTest.class);
+		addJava10Tests(tests_11);
 		// Reset forgotten subsets tests
 		TestCase.TESTS_PREFIX = null;
 		TestCase.TESTS_NAMES = null;
@@ -188,17 +158,7 @@
 	if ((possibleComplianceLevels & AbstractCompilerTest.F_12) != 0) {
 		ArrayList tests_12 = (ArrayList)testClasses.clone();
 		tests_12.addAll(TEST_CLASSES_1_5);
-		tests_12.add(ParserTest1_7.class);
-		tests_12.add(LambdaExpressionSyntaxTest.class);
-		tests_12.add(ReferenceExpressionSyntaxTest.class);
-		tests_12.add(TypeAnnotationSyntaxTest.class);
-		tests_12.add(CompletionParserTest18.class);
-		tests_12.add(SelectionParserTest18.class);
-		tests_12.add(SelectionParserTest9.class);
-		tests_12.add(SelectionParserTest10.class);
-		tests_12.add(SelectionParserTest12.class);
-		tests_12.add(ModuleDeclarationSyntaxTest.class);
-		tests_12.add(JEP286ReservedWordTest.class);
+		addJava12Tests(tests_12);
 		// Reset forgotten subsets tests
 		TestCase.TESTS_PREFIX = null;
 		TestCase.TESTS_NAMES = null;
@@ -210,17 +170,7 @@
 	if ((possibleComplianceLevels & AbstractCompilerTest.F_13) != 0) {
 		ArrayList tests_13 = (ArrayList)testClasses.clone();
 		tests_13.addAll(TEST_CLASSES_1_5);
-		tests_13.add(ParserTest1_7.class);
-		tests_13.add(LambdaExpressionSyntaxTest.class);
-		tests_13.add(ReferenceExpressionSyntaxTest.class);
-		tests_13.add(TypeAnnotationSyntaxTest.class);
-		tests_13.add(CompletionParserTest18.class);
-		tests_13.add(SelectionParserTest18.class);
-		tests_13.add(SelectionParserTest9.class);
-		tests_13.add(SelectionParserTest10.class);
-		tests_13.add(SelectionParserTest12.class);
-		tests_13.add(ModuleDeclarationSyntaxTest.class);
-		tests_13.add(JEP286ReservedWordTest.class);
+		addJava12Tests(tests_13);
 		//TODO:To add SwitchExpressionYieldTests here as well as master
 		// Reset forgotten subsets tests
 		TestCase.TESTS_PREFIX = null;
@@ -233,17 +183,7 @@
 	if ((possibleComplianceLevels & AbstractCompilerTest.F_14) != 0) {
 		ArrayList tests_14 = (ArrayList)testClasses.clone();
 		tests_14.addAll(TEST_CLASSES_1_5);
-		tests_14.add(ParserTest1_7.class);
-		tests_14.add(LambdaExpressionSyntaxTest.class);
-		tests_14.add(ReferenceExpressionSyntaxTest.class);
-		tests_14.add(TypeAnnotationSyntaxTest.class);
-		tests_14.add(CompletionParserTest18.class);
-		tests_14.add(SelectionParserTest18.class);
-		tests_14.add(SelectionParserTest9.class);
-		tests_14.add(SelectionParserTest10.class);
-		tests_14.add(SelectionParserTest12.class);
-		tests_14.add(ModuleDeclarationSyntaxTest.class);
-		tests_14.add(JEP286ReservedWordTest.class);
+		addJava12Tests(tests_14);
 		// Reset forgotten subsets tests
 		TestCase.TESTS_PREFIX = null;
 		TestCase.TESTS_NAMES = null;
@@ -255,17 +195,7 @@
 	if ((possibleComplianceLevels & AbstractCompilerTest.F_15) != 0) {
 		ArrayList tests_15 = (ArrayList)testClasses.clone();
 		tests_15.addAll(TEST_CLASSES_1_5);
-		tests_15.add(ParserTest1_7.class);
-		tests_15.add(LambdaExpressionSyntaxTest.class);
-		tests_15.add(ReferenceExpressionSyntaxTest.class);
-		tests_15.add(TypeAnnotationSyntaxTest.class);
-		tests_15.add(CompletionParserTest18.class);
-		tests_15.add(SelectionParserTest18.class);
-		tests_15.add(SelectionParserTest9.class);
-		tests_15.add(SelectionParserTest10.class);
-		tests_15.add(SelectionParserTest12.class);
-		tests_15.add(ModuleDeclarationSyntaxTest.class);
-		tests_15.add(JEP286ReservedWordTest.class);
+		addJava12Tests(tests_15);
 		// Reset forgotten subsets tests
 		TestCase.TESTS_PREFIX = null;
 		TestCase.TESTS_NAMES = null;
@@ -277,18 +207,7 @@
 	if ((possibleComplianceLevels & AbstractCompilerTest.F_16) != 0) {
 		ArrayList tests_16 = (ArrayList)testClasses.clone();
 		tests_16.addAll(TEST_CLASSES_1_5);
-		tests_16.add(ParserTest1_7.class);
-		tests_16.add(LambdaExpressionSyntaxTest.class);
-		tests_16.add(ReferenceExpressionSyntaxTest.class);
-		tests_16.add(TypeAnnotationSyntaxTest.class);
-		tests_16.add(CompletionParserTest18.class);
-		tests_16.add(SelectionParserTest18.class);
-		tests_16.add(SelectionParserTest9.class);
-		tests_16.add(SelectionParserTest10.class);
-		tests_16.add(SelectionParserTest12.class);
-		tests_16.add(ModuleDeclarationSyntaxTest.class);
-		tests_16.add(JEP286ReservedWordTest.class);
-		tests_16.add(PatternMatchingSelectionTest.class);
+		addJava16Tests(tests_16);
 		// Reset forgotten subsets tests
 		TestCase.TESTS_PREFIX = null;
 		TestCase.TESTS_NAMES = null;
@@ -301,18 +220,7 @@
 	if ((possibleComplianceLevels & AbstractCompilerTest.F_17) != 0) {
 		ArrayList tests_17 = (ArrayList)testClasses.clone();
 		tests_17.addAll(TEST_CLASSES_1_5);
-		tests_17.add(ParserTest1_7.class);
-		tests_17.add(LambdaExpressionSyntaxTest.class);
-		tests_17.add(ReferenceExpressionSyntaxTest.class);
-		tests_17.add(TypeAnnotationSyntaxTest.class);
-		tests_17.add(CompletionParserTest18.class);
-		tests_17.add(SelectionParserTest18.class);
-		tests_17.add(SelectionParserTest9.class);
-		tests_17.add(SelectionParserTest10.class);
-		tests_17.add(SelectionParserTest12.class);
-		tests_17.add(ModuleDeclarationSyntaxTest.class);
-		tests_17.add(JEP286ReservedWordTest.class);
-		tests_17.add(PatternMatchingSelectionTest.class);
+		addJava16Tests(tests_17);
 		// Reset forgotten subsets tests
 		TestCase.TESTS_PREFIX = null;
 		TestCase.TESTS_NAMES = null;
@@ -321,8 +229,51 @@
 		TestCase.RUN_ONLY_ID = null;
 		all.addTest(AbstractCompilerTest.buildComplianceTestSuite(ClassFileConstants.getComplianceLevelForJavaVersion(ClassFileConstants.MAJOR_VERSION_17), tests_17));
 	}
+	if ((possibleComplianceLevels & AbstractCompilerTest.F_18) != 0) {
+		ArrayList tests_18 = (ArrayList)testClasses.clone();
+		tests_18.addAll(TEST_CLASSES_1_5);
+		addJava16Tests(tests_18);
+		// Reset forgotten subsets tests
+		TestCase.TESTS_PREFIX = null;
+		TestCase.TESTS_NAMES = null;
+		TestCase.TESTS_NUMBERS= null;
+		TestCase.TESTS_RANGE = null;
+		TestCase.RUN_ONLY_ID = null;
+		all.addTest(AbstractCompilerTest.buildComplianceTestSuite(ClassFileConstants.getComplianceLevelForJavaVersion(ClassFileConstants.MAJOR_VERSION_18), tests_18));
+	}
 	return all;
 }
+
+private static void addJava16Tests(ArrayList tests_16) {
+	addJava1_8Tests(tests_16);
+	tests_16.add(PatternMatchingSelectionTest.class);
+}
+
+private static void addJava12Tests(ArrayList tests_12) {
+	addJava10Tests(tests_12);
+	tests_12.add(SelectionParserTest12.class);
+}
+
+private static void addJava10Tests(ArrayList tests_10) {
+	addJava9Tests(tests_10);
+	tests_10.add(SelectionParserTest10.class);
+	tests_10.add(JEP286ReservedWordTest.class);
+}
+
+private static void addJava9Tests(ArrayList tests_9) {
+	addJava1_8Tests(tests_9);
+	tests_9.add(SelectionParserTest9.class);
+	tests_9.add(ModuleDeclarationSyntaxTest.class);
+}
+
+private static void addJava1_8Tests(ArrayList tests_1_8) {
+	tests_1_8.add(ParserTest1_7.class);
+	tests_1_8.add(LambdaExpressionSyntaxTest.class);
+	tests_1_8.add(ReferenceExpressionSyntaxTest.class);
+	tests_1_8.add(TypeAnnotationSyntaxTest.class);
+	tests_1_8.add(CompletionParserTest18.class);
+	tests_1_8.add(SelectionParserTest18.class);
+}
 public static Test suite() {
 	return getTestSuite(true);
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractNullAnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractNullAnnotationTest.java
index b4cb3e7..0024a9b 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractNullAnnotationTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractNullAnnotationTest.java
@@ -92,7 +92,7 @@
 			System.arraycopy(defaultLibs, 0, this.LIBS, 0, len);
 			String version = this.complianceLevel >= ClassFileConstants.JDK1_8 ? "[2.0.0,3.0.0)" : "[1.1.0,2.0.0)";
 			Bundle[] bundles = org.eclipse.jdt.core.tests.compiler.Activator.getPackageAdmin().getBundles("org.eclipse.jdt.annotation", version);
-			File bundleFile = FileLocator.getBundleFile(bundles[0]);
+			File bundleFile = FileLocator.getBundleFileLocation(bundles[0]).get();
 			if (bundleFile.isDirectory())
 				this.LIBS[len] = bundleFile.getPath()+"/bin";
 			else
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java
index 4cde8bd..42e5eac 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java
@@ -1717,14 +1717,14 @@
 		return DefaultJavaRuntimeEnvironment.getDefaultClassPaths();
 	}
 	/** Get class library paths built from default class paths plus the JDT null annotations. */
-	protected String[] getLibsWithNullAnnotations(long sourceLevel) throws IOException {
+	protected String[] getLibsWithNullAnnotations(long sourceLevel) {
 		String[] defaultLibs = getDefaultClassPaths();
 		int len = defaultLibs.length;
 		String[] libs = new String[len+1];
 		System.arraycopy(defaultLibs, 0, libs, 0, len);
 		String version = sourceLevel < ClassFileConstants.JDK1_8 ? "[1.1.0,2.0.0)" : "[2.0.0,3.0.0)";
 		Bundle[] bundles = Platform.getBundles("org.eclipse.jdt.annotation", version);
-		File bundleFile = FileLocator.getBundleFile(bundles[0]);
+		File bundleFile = FileLocator.getBundleFileLocation(bundles[0]).get();
 		if (bundleFile.isDirectory())
 			libs[len] = bundleFile.getPath()+"/bin";
 		else
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
index 14fcadf..2f90961 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2021 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -12895,6 +12895,66 @@
 	        "1 problem (1 warning)\n",
 			true);
 }
+public void testBug574425() {
+	String path = LIB_DIR;
+	String libPath = null;
+	if (path.endsWith(File.separator)) {
+		libPath = path + "lib.jar";
+	} else {
+		libPath = path + File.separator + "lib.jar";
+	}
+	try {
+		Util.createJar(
+				new String[] {
+						"org/apache/accumulo/core/conf/Property.java",
+						"package org.apache.accumulo.core.conf;\n"
+						+ "import java.lang.annotation.Inherited;\n"
+						+ "import java.lang.annotation.Retention;\n"
+						+ "import java.lang.annotation.RetentionPolicy;\n"
+						+ "public enum Property {\n"
+						+ "	@Deprecated(since = \"2.1.0\")\n"
+						+ "	TSERV_WAL_SORT_MAX_CONCURRENT(\"tserver.wal.sort.concurrent.max\", \"2\", \"2\",\n"
+						+ "			\"The maximum number of threads to use to sort logs during recovery\", \"2.1.0\"),\n"
+						+ "	@Deprecated(since = \"2.1.0\")\n"
+						+ "	@ReplacedBy(property = Property.TSERV_WAL_SORT_MAX_CONCURRENT) \n"
+						+ "	TSERV_RECOVERY_MAX_CONCURRENT(\"tserver.recovery.concurrent.max\", \"2\", \"2\",\n"
+						+ "			\"The maximum number of threads to use to sort logs during recovery\", \"1.5.0\"),\n"
+						+ "	RPC_SSL_KEYSTORE_PASSWORD(\"rpc.javax.net.ssl.keyStorePassword\", \"\", \"2\",\n"
+						+ "			\"Password used to encrypt the SSL private keystore. \" + \"Leave blank to use the Accumulo instance secret\",\n"
+						+ "			\"1.6.0\"); \n"
+						+ "  Property(String name, String defaultValue, String type, String description,\n"
+						+ "      String availableSince) {\n"
+						+ "  }\n"
+						+ "}\n"
+						+ "@Inherited\n"
+						+ "@Retention(RetentionPolicy.RUNTIME)\n"
+						+ "@interface ReplacedBy { \n"
+						+ "  Property property();\n"
+						+ "}\n"
+				},
+				null,
+				libPath,
+				JavaCore.VERSION_1_8);
+		this.runConformTest(
+				new String[] {
+						"src/org/apache/accumulo/test/fate/zookeeper/X.java",
+						"package org.apache.accumulo.test.fate.zookeeper;\n"
+						+ "import org.apache.accumulo.core.conf.Property;\n"
+						+ "public class X {\n"
+						+ "}\n",
+				},
+				"\"" + OUTPUT_DIR +  File.separator + "src/org/apache/accumulo/test/fate/zookeeper/X.java\""
+				+ " -classpath \"" + libPath + "\""
+				+ " -1.8 -nowarn"
+				+ " -d \"" + OUTPUT_DIR + File.separator + "bin\" ",
+				"",
+				"",
+		        true);
+	} catch (IOException e) {
+	} finally {
+		Util.delete(libPath);
+	}
+}
 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=419351
 public void testBug419351() {
 	String backup = System.getProperty("java.endorsed.dirs");
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 8904200..e6f811b 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
@@ -779,6 +779,12 @@
 		expectedProblemAttributes.put("JavadocUndefinedType", new ProblemAttributes(CategorizedProblem.CAT_JAVADOC));
 		expectedProblemAttributes.put("JavadocUnexpectedTag", new ProblemAttributes(CategorizedProblem.CAT_JAVADOC));
 		expectedProblemAttributes.put("JavadocUnexpectedText", new ProblemAttributes(CategorizedProblem.CAT_JAVADOC));
+		expectedProblemAttributes.put("JavadocInvalidSnippet", new ProblemAttributes(CategorizedProblem.CAT_JAVADOC));
+		expectedProblemAttributes.put("JavadocInvalidSnippetMissingColon", new ProblemAttributes(CategorizedProblem.CAT_JAVADOC));
+		expectedProblemAttributes.put("JavadocInvalidSnippetContentNewLine", new ProblemAttributes(CategorizedProblem.CAT_JAVADOC));
+		expectedProblemAttributes.put("JavadocInvalidSnippetRegionNotClosed", new ProblemAttributes(CategorizedProblem.CAT_JAVADOC));
+		expectedProblemAttributes.put("JavadocInvalidSnippetRegexSubstringTogether", new ProblemAttributes(CategorizedProblem.CAT_JAVADOC));
+		expectedProblemAttributes.put("JavadocInvalidSnippetDuplicateRegions", new ProblemAttributes(CategorizedProblem.CAT_JAVADOC));
 		expectedProblemAttributes.put("JavadocUnterminatedInlineTag", new ProblemAttributes(CategorizedProblem.CAT_JAVADOC));
 		expectedProblemAttributes.put("JavadocUsingDeprecatedConstructor", new ProblemAttributes(CategorizedProblem.CAT_JAVADOC));
 		expectedProblemAttributes.put("JavadocUsingDeprecatedField", new ProblemAttributes(CategorizedProblem.CAT_JAVADOC));
@@ -1943,6 +1949,12 @@
 		expectedProblemAttributes.put("JavadocUndefinedType", new ProblemAttributes(JavaCore.COMPILER_PB_INVALID_JAVADOC));
 		expectedProblemAttributes.put("JavadocUnexpectedTag", new ProblemAttributes(JavaCore.COMPILER_PB_INVALID_JAVADOC));
 		expectedProblemAttributes.put("JavadocUnexpectedText", new ProblemAttributes(JavaCore.COMPILER_PB_INVALID_JAVADOC));
+		expectedProblemAttributes.put("JavadocInvalidSnippet", new ProblemAttributes(JavaCore.COMPILER_PB_INVALID_JAVADOC));
+		expectedProblemAttributes.put("JavadocInvalidSnippetMissingColon", new ProblemAttributes(JavaCore.COMPILER_PB_INVALID_JAVADOC));
+		expectedProblemAttributes.put("JavadocInvalidSnippetContentNewLine", new ProblemAttributes(JavaCore.COMPILER_PB_INVALID_JAVADOC));
+		expectedProblemAttributes.put("JavadocInvalidSnippetRegionNotClosed", new ProblemAttributes(JavaCore.COMPILER_PB_INVALID_JAVADOC));
+		expectedProblemAttributes.put("JavadocInvalidSnippetRegexSubstringTogether", new ProblemAttributes(JavaCore.COMPILER_PB_INVALID_JAVADOC));
+		expectedProblemAttributes.put("JavadocInvalidSnippetDuplicateRegions", new ProblemAttributes(JavaCore.COMPILER_PB_INVALID_JAVADOC));
 		expectedProblemAttributes.put("JavadocUnterminatedInlineTag", new ProblemAttributes(JavaCore.COMPILER_PB_INVALID_JAVADOC));
 		expectedProblemAttributes.put("JavadocUsingDeprecatedConstructor", new ProblemAttributes(JavaCore.COMPILER_PB_INVALID_JAVADOC));
 		expectedProblemAttributes.put("JavadocUsingDeprecatedField", new ProblemAttributes(JavaCore.COMPILER_PB_INVALID_JAVADOC));
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 ea2c13e..5aa8de7 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
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2021 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -5413,7 +5413,6 @@
 		if (this.complianceLevel < ClassFileConstants.JDK17)
 			return;
 		Map customOptions = getCompilerOptions();
-		customOptions.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
 		customOptions.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.WARNING);
 		this.runNegativeTest(
 			new String[] {
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocBugsTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocBugsTest.java
index 3f8d433..5dfe426 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocBugsTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocBugsTest.java
@@ -8500,6 +8500,15 @@
 					}
 				}
 			}
+			for (int i=0; i < JavadocTagConstants.IN_SNIPPET_TAGS_LENGTH; i++) {
+				int length = JavadocTagConstants.IN_SNIPPET_TAGS[i].length;
+				for (int j=0; j < length; j++) {
+					if (tagName == JavadocTagConstants.IN_SNIPPET_TAGS[i][j]) {
+						assertEquals(JavadocTagConstants.JAVADOC_TAG_TYPE[index], JavadocTagConstants.TAG_TYPE_IN_SNIPPET);
+						continue nextTag;
+					}
+				}
+			}
 		}
 		assertEquals(JavadocTagConstants.JAVADOC_TAG_TYPE[index], JavadocTagConstants.TAG_TYPE_NONE);
 	}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocTest_18.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocTest_18.java
new file mode 100644
index 0000000..8f3ebc1
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocTest_18.java
@@ -0,0 +1,374 @@
+/*******************************************************************************
+ * Copyright (c) 2022 IBM Corporation 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
+ *******************************************************************************/
+package org.eclipse.jdt.core.tests.compiler.regression;
+
+import java.util.Map;
+
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+
+import junit.framework.Test;
+
+
+@SuppressWarnings({ "unchecked", "rawtypes" })
+public class JavadocTest_18 extends JavadocTest {
+
+	String docCommentSupport = CompilerOptions.ENABLED;
+	String reportInvalidJavadoc = CompilerOptions.ERROR;
+	String reportMissingJavadocDescription = CompilerOptions.RETURN_TAG;
+	String reportInvalidJavadocVisibility = CompilerOptions.PRIVATE;
+	String reportMissingJavadocTags = CompilerOptions.ERROR;
+	String reportMissingJavadocComments = null;
+	String reportMissingJavadocCommentsVisibility = null;
+	String reportDeprecation = CompilerOptions.ERROR;
+	String reportJavadocDeprecation = null;
+	String processAnnotations = null;
+
+public JavadocTest_18(String name) {
+	super(name);
+}
+
+public static Class javadocTestClass() {
+	return JavadocTest_18.class;
+}
+
+// Use this static initializer to specify subset for tests
+// All specified tests which does not belong to the class are skipped...
+static {
+
+}
+
+public static Test suite() {
+	return buildMinimalComplianceTestSuite(javadocTestClass(), F_18);
+}
+
+@Override
+protected Map getCompilerOptions() {
+	Map options = super.getCompilerOptions();
+	options.put(CompilerOptions.OPTION_DocCommentSupport, this.docCommentSupport);
+	options.put(CompilerOptions.OPTION_ReportInvalidJavadoc, this.reportInvalidJavadoc);
+	if (!CompilerOptions.IGNORE.equals(this.reportInvalidJavadoc)) {
+		options.put(CompilerOptions.OPTION_ReportInvalidJavadocTagsVisibility, this.reportInvalidJavadocVisibility);
+	}
+	if (this.reportJavadocDeprecation != null) {
+		options.put(CompilerOptions.OPTION_ReportInvalidJavadocTagsDeprecatedRef, this.reportJavadocDeprecation);
+	}
+	if (this.reportMissingJavadocComments != null) {
+		options.put(CompilerOptions.OPTION_ReportMissingJavadocComments, this.reportMissingJavadocComments);
+		options.put(CompilerOptions.OPTION_ReportMissingJavadocCommentsOverriding, CompilerOptions.ENABLED);
+		if (this.reportMissingJavadocCommentsVisibility != null) {
+			options.put(CompilerOptions.OPTION_ReportMissingJavadocCommentsVisibility, this.reportMissingJavadocCommentsVisibility);
+		}
+	} else {
+		options.put(CompilerOptions.OPTION_ReportMissingJavadocComments, this.reportInvalidJavadoc);
+	}
+	if (this.reportMissingJavadocTags != null) {
+		options.put(CompilerOptions.OPTION_ReportMissingJavadocTags, this.reportMissingJavadocTags);
+		options.put(CompilerOptions.OPTION_ReportMissingJavadocTagsOverriding, CompilerOptions.ENABLED);
+	} else {
+		options.put(CompilerOptions.OPTION_ReportMissingJavadocTags, this.reportInvalidJavadoc);
+	}
+	if (this.reportMissingJavadocDescription != null) {
+		options.put(CompilerOptions.OPTION_ReportMissingJavadocTagDescription, this.reportMissingJavadocDescription);
+	}
+	if (this.processAnnotations != null) {
+		options.put(CompilerOptions.OPTION_Process_Annotations, this.processAnnotations);
+	}
+	options.put(CompilerOptions.OPTION_ReportFieldHiding, CompilerOptions.IGNORE);
+	options.put(CompilerOptions.OPTION_ReportSyntheticAccessEmulation, CompilerOptions.IGNORE);
+	options.put(CompilerOptions.OPTION_ReportDeprecation, this.reportDeprecation);
+	options.put(CompilerOptions.OPTION_ReportUnusedImport, CompilerOptions.ERROR);
+	options.put(CompilerOptions.OPTION_ReportRawTypeReference, CompilerOptions.IGNORE);
+	options.put(CompilerOptions.OPTION_ReportUnusedPrivateMember, CompilerOptions.IGNORE);
+	return options;
+}
+/* (non-Javadoc)
+ * @see junit.framework.TestCase#setUp()
+ */
+@Override
+protected void setUp() throws Exception {
+	super.setUp();
+	this.docCommentSupport = CompilerOptions.ENABLED;
+	this.reportInvalidJavadoc = CompilerOptions.ERROR;
+	this.reportInvalidJavadocVisibility = CompilerOptions.PRIVATE;
+	this.reportMissingJavadocTags = CompilerOptions.IGNORE;
+	this.reportMissingJavadocComments = CompilerOptions.IGNORE;
+	this.reportMissingJavadocCommentsVisibility = CompilerOptions.PUBLIC;
+	this.reportDeprecation = CompilerOptions.ERROR;
+	this.reportInvalidJavadoc = CompilerOptions.ERROR;
+}
+
+
+
+public void test001() {
+	if(this.complianceLevel < ClassFileConstants.JDK18) {
+		return;
+	}
+	this.runNegativeTest(
+		new String[] {
+			"X.java",
+				" /**\n"
+				+ " * {@snippet : public static void main(String... args) {\n"
+				+ " *       for (var arg : args) {                 \n"
+				+ " *           if (!arg.isBlank()) {\n"
+				+ " *               System.out.println(arg);\n"
+				+ " *           }\n"
+				+ " *       }                                      \n"
+				+ " *   }\n"
+				+ " *   }\n"
+				+ " */\n"
+				+ "public class X {\n"
+				+ "}",
+		},
+		"----------\n" +
+				"1. ERROR in X.java (at line 2)\n" +
+				"	* {@snippet : public static void main(String... args) {\n" +
+				"	              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+				"Javadoc: Snippet content should be on a new line\n" +
+				"----------\n",
+
+			JavacTestOptions.Excuse.EclipseWarningConfiguredAsError
+	);
+}
+
+public void test002() {
+	if(this.complianceLevel < ClassFileConstants.JDK18) {
+		return;
+	}
+	this.runNegativeTest(
+		new String[] {
+			"X.java",
+				" /**\n"
+				+ " * {@snippet : "
+				+ " * public static void main(String... args) {\n"
+				+ " *       for (var arg : args) {                 \n"
+				+ " *           if (!arg.isBlank()) {\n"
+				+ " *               System.out.println(arg);\n"
+				+ " *           }\n"
+				+ " *       }                                      \n"
+				+ " *   }\n"
+				+ " *   }\n"
+				+ " */\n"
+				+ "public class X {\n"
+				+ "}",
+		},
+		null,
+			JavacTestOptions.Excuse.EclipseWarningConfiguredAsError
+	);
+}
+
+public void test003() {
+	if(this.complianceLevel < ClassFileConstants.JDK18) {
+		return;
+	}
+	this.runNegativeTest(
+		new String[] {
+			"X.java",
+				" /**\n"
+				+ " * {@snippet:\n"
+				+ " *abcd                  \n"
+				+ " */\n"
+				+ "public class X {\n"
+				+ "}",
+		},
+		"----------\n" +
+				"1. ERROR in X.java (at line 2)\n" +
+				"	* {@snippet:\n" +
+				"	  ^^^^^^^^^^\n" +
+				"Javadoc: Missing closing brace for inline tag\n" +
+				"----------\n" +
+				"2. ERROR in X.java (at line 2)\n" +
+				"	* {@snippet:\n" +
+				"	    ^^^^^^^^\n" +
+				"Javadoc: Space required after snippet tag\n" +
+				"----------\n",
+			JavacTestOptions.Excuse.EclipseWarningConfiguredAsError
+	);
+}
+
+public void test004() {
+	if(this.complianceLevel < ClassFileConstants.JDK18) {
+		return;
+	}
+	this.runConformTest(
+		new String[] {
+			"X.java",
+				" /**\n"
+				+ " * {@snippet :\n"
+				+ " *abcd   }               \n"
+				+ " */\n"
+				+ "public class X {\n"
+				+ "}",
+		}
+	);
+}
+
+public void test005() {
+	if(this.complianceLevel < ClassFileConstants.JDK18) {
+		return;
+	}
+	this.runNegativeTest(
+		new String[] {
+			"X.java",
+				" /**\n"
+				+ " * {@snippet :\n"
+				+ " * while(true){{{             \n"
+				+ " * }             \n"
+				+ " */\n"
+				+ "public class X {\n"
+				+ "}",
+		},
+		"----------\n" +
+		"1. ERROR in X.java (at line 2)\n" +
+		"	* {@snippet :\n" +
+		"	  ^^^^^^^^^^^\n" +
+		"Javadoc: Missing closing brace for inline tag\n" +
+		"----------\n"
+	,
+			JavacTestOptions.Excuse.EclipseWarningConfiguredAsError
+	);
+}
+
+public void test006() {
+	if(this.complianceLevel < ClassFileConstants.JDK18) {
+		return;
+	}
+	this.runNegativeTest(
+		new String[] {
+			"X.java",
+				" /**\n"
+				+ " * {@snippet \n"
+				+ " *              \n"
+				+ " * }             \n"
+				+ " */\n"
+				+ "public class X {\n"
+				+ "}",
+		},
+		"----------\n" +
+		"1. ERROR in X.java (at line 4)\n" +
+		"	* }             \n" +
+		"	   ^^^^^^^^^^^^^\n" +
+		"Javadoc: Snippet is invalid due to missing colon\n" +
+		"----------\n",
+
+			JavacTestOptions.Excuse.EclipseWarningConfiguredAsError
+	);
+}
+public void test007() {
+	if(this.complianceLevel < ClassFileConstants.JDK18) {
+		return;
+	}
+	this.runNegativeTest(
+		new String[] {
+			"X.java",
+				" /**\n"
+				+ " * {@snippet \n"
+				+ " *              \n"
+				+ " * }             \n"
+				+ " */\n"
+				+ "public class X {\n"
+				+ "}",
+		},
+		"----------\n" +
+				"1. ERROR in X.java (at line 4)\n" +
+				"	* }             \n" +
+				"	   ^^^^^^^^^^^^^\n" +
+				"Javadoc: Snippet is invalid due to missing colon\n" +
+				"----------\n",
+
+			JavacTestOptions.Excuse.EclipseWarningConfiguredAsError
+	);
+}
+
+public void test008() {
+	if(this.complianceLevel < ClassFileConstants.JDK18) {
+		return;
+	}
+	this.runNegativeTest(
+		new String[] {
+			"X.java",
+				" /**\n"
+				+ " * {@snippet : \n"
+				+ " *     abc // @replace substring='a'  regex='a'       \n"
+				+ " * }             \n"
+				+ " */\n"
+				+ "public class X {\n"
+				+ "}",
+		},
+		"----------\n" +
+				"1. ERROR in X.java (at line 3)\n" +
+				"	*     abc // @replace substring=\'a\'  regex=\'a\'       \n" +
+				"	          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+				"Javadoc: Attribute regex and substring used simulataneously\n" +
+				"----------\n",
+
+			JavacTestOptions.Excuse.EclipseWarningConfiguredAsError
+	);
+}
+public void test009() {
+	if(this.complianceLevel < ClassFileConstants.JDK18) {
+		return;
+	}
+	this.runNegativeTest(
+		new String[] {
+			"X.java",
+				" /**\n"
+				+ " * {@snippet : \n"
+				+ " *     abc // @highlight substring='a'  region='abcd'      \n"
+				+ " *      //@end region='abc'        \n"
+				+ " * }             \n"
+				+ " */\n"
+				+ "public class X {\n"
+				+ "}",
+		},
+		"----------\n" +
+				"1. ERROR in X.java (at line 5)\n" +
+				"	* }             \n" +
+				"	   ^^^^^^^^^^^^^\n" +
+				"Javadoc: Region in the snippet is not closed\n" +
+				"----------\n",
+
+			JavacTestOptions.Excuse.EclipseWarningConfiguredAsError
+	);
+}
+public void test010() {
+	if(this.complianceLevel < ClassFileConstants.JDK18) {
+		return;
+	}
+	this.runNegativeTest(
+		new String[] {
+			"X.java",
+				" /**\n"
+				+ " * {@snippet : \n"
+				+ " *     abc // @highlight substring='a'  region='abcd'      \n"
+				+ " *     abc // @highlight substring='a'  region='abcd'      \n"
+				+ " *      //@end region='abcd'        \n"
+				+ " *      //@end region='abcd'        \n"
+				+ " * }             \n"
+				+ " */\n"
+				+ "public class X {\n"
+				+ "}",
+		},
+		"----------\n" +
+				"1. ERROR in X.java (at line 4)\n" +
+				"	*     abc // @highlight substring=\'a\'  region=\'abcd\'      \n" +
+				"	                                       ^^^^^^\n" +
+				"Javadoc: Duplicate region\n" +
+				"----------\n",
+
+			JavacTestOptions.Excuse.EclipseWarningConfiguredAsError
+	);
+}
+}
+
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTests17.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTests18.java
similarity index 98%
rename from org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTests17.java
rename to org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTests18.java
index 95e3ea4..b3b087f 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTests17.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTests18.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2021 GK Software SE, and others.
+ * Copyright (c) 2021, 2022 GK Software SE, and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -24,9 +24,9 @@
 
 import junit.framework.Test;
 
-public class NullAnnotationTests17 extends AbstractNullAnnotationTest {
+public class NullAnnotationTests18 extends AbstractNullAnnotationTest {
 
-	public NullAnnotationTests17(String name) {
+	public NullAnnotationTests18(String name) {
 		super(name);
 	}
 
@@ -37,11 +37,11 @@
 	}
 
 	public static Test suite() {
-		return buildMinimalComplianceTestSuite(testClass(), F_17);
+		return buildMinimalComplianceTestSuite(testClass(), F_18);
 	}
 
 	public static Class<?> testClass() {
-		return NullAnnotationTests17.class;
+		return NullAnnotationTests18.class;
 	}
 
 	@Deprecated // super method is deprecated
@@ -118,7 +118,7 @@
 			null,
 			jarFileName,
 			jcl17Path != null ? new String[] { jcl17Path } : null,
-			"17");
+			"18");
 		return jarFileName;
 	}
 
@@ -128,7 +128,7 @@
 		Runner runner = new Runner();
 		runner.classLibraries = this.LIBS;
 		Map<String,String> opts = getCompilerOptions();
-		opts.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_17);
+		opts.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_18);
 		opts.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
 		opts.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
 		runner.customOptions = opts;
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTestAsserts.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTestAsserts.java
index 79c282c..a9f5080 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTestAsserts.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTestAsserts.java
@@ -150,7 +150,7 @@
 		int len = defaultLibs.length;
 		this.assertLib = new String[len+1];
 		System.arraycopy(defaultLibs, 0, this.assertLib, 0, len);
-		File bundleFile = FileLocator.getBundleFile(Platform.getBundle("org.eclipse.equinox.common"));
+		File bundleFile = FileLocator.getBundleFileLocation(Platform.getBundle("org.eclipse.equinox.common")).get();
 		if (bundleFile.isDirectory())
 			this.assertLib[len] = bundleFile.getPath()+"/bin";
 		else
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PatternMatching16Test.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PatternMatching16Test.java
index 4188240..f4a7fea 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PatternMatching16Test.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PatternMatching16Test.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2020, 2021 IBM Corporation and others.
+ * Copyright (c) 2020, 2022 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
@@ -120,7 +120,7 @@
 				"1. ERROR in X1.java (at line 0)\n" +
 				"	public class X1 {\n" +
 				"	^\n" +
-				"Preview features enabled at an invalid source release level 14, preview can be enabled only at source level 17\n" +
+				"Preview features enabled at an invalid source release level 14, preview can be enabled only at source level "+PREVIEW_ALLOWED_LEVEL+"\n" +
 				"----------\n",
 				null,
 				true,
@@ -3990,4 +3990,101 @@
                 options);
 
     }
+	public void testBug578628_1() {
+		if (this.complianceLevel < ClassFileConstants.JDK18)
+			return;
+		Map<String, String> compilerOptions = getCompilerOptions(true);
+		runConformTest(
+				new String[] {
+						"X.java",
+							"public class X {\n"
+							+ "    public static Object str = \"a\";\n"
+							+ "    public static void foo() {\n"
+							+ "    	if (str instanceof (String a && a == null)) {\n"
+							+ "            System.out.println(true);\n"
+							+ "        } else {\n"
+							+ "        	System.out.println(false);\n"
+							+ "        }\n"
+							+ "    } \n"
+							+ "    public static void main(String[] argv) {\n"
+							+ "    	foo();\n"
+							+ "    }\n"
+							+ "}",
+				},
+				"false",
+				compilerOptions);
+	}
+	public void testBug578628_2() {
+		if (this.complianceLevel < ClassFileConstants.JDK18)
+			return;
+		Map<String, String> compilerOptions = getCompilerOptions(true);
+		runConformTest(
+				new String[] {
+						"X.java",
+							"public class X {\n"
+							+ "    public static Object str = \"a\";\n"
+							+ "    public static void foo() {\n"
+							+ "    	if (str instanceof (String a && a != null)) {\n"
+							+ "            System.out.println(true);\n"
+							+ "        } else {\n"
+							+ "        	System.out.println(false);\n"
+							+ "        }\n"
+							+ "    } \n"
+							+ "    public static void main(String[] argv) {\n"
+							+ "    	foo();\n"
+							+ "    }\n"
+							+ "}",
+				},
+				"true",
+				compilerOptions);
+	}
+	public void testBug578628_3() {
+		if (this.complianceLevel < ClassFileConstants.JDK18)
+			return;
+		Map<String, String> compilerOptions = getCompilerOptions(true);
+		runConformTest(
+				new String[] {
+						"X.java",
+							"public class X {\n"
+							+ "    public static Object str = \"a\";\n"
+							+ "    public static void foo() {\n"
+							+ "    	bar(str instanceof (String a && a == null));\n"
+							+ "    } \n"
+							+ "    public static void bar(boolean arg) {\n"
+							+ "    	System.out.println(arg);\n"
+							+ "    }\n"
+							+ "    public static void main(String[] argv) {\n"
+							+ "    	foo();\n"
+							+ "    }\n"
+							+ "}",
+				},
+				"false",
+				compilerOptions);
+	}
+	public void testBug578628_4() {
+		if (this.complianceLevel < ClassFileConstants.JDK18)
+			return;
+		Map<String, String> compilerOptions = getCompilerOptions(true);
+		runConformTest(
+				new String[] {
+						"X.java",
+							"public class X {\n"
+							+ "    public static Object str = \"a\";\n"
+							+ "public static void foo() {\n"
+							+ "    	boolean b = switch (str) {\n"
+							+ "    		case String s -> {\n"
+							+ "    			yield (str instanceof (String a && a != null));\n"
+							+ "    		}\n"
+							+ "    		default -> false;\n"
+							+ "    	};\n"
+							+ "    	System.out.println(b);\n"
+							+ "    }\n"
+							+ "    public static void main(String[] argv) {\n"
+							+ "    	foo();\n"
+							+ "    }\n"
+							+ "}",
+				},
+				"true",
+				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 21aa996..51a5471 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
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2019, 2021 IBM Corporation and others.
+ * Copyright (c) 2019, 2022 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
@@ -54,14 +54,14 @@
 		return defaultOptions;
 	}
 	// Enables the tests to run individually
-	protected Map<String, String> getCompilerOptionsWithPreview() {
+	protected Map<String, String> getCompilerOptionsWithPreviewIfApplicable() {
 		Map<String, String> defaultOptions = super.getCompilerOptions();
 		defaultOptions.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_17);
 		defaultOptions.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_17);
 		defaultOptions.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_17);
 		defaultOptions.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
 		defaultOptions.put(CompilerOptions.OPTION_Store_Annotations, CompilerOptions.ENABLED);
-		defaultOptions.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
+		defaultOptions.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.DISABLED);
 		return defaultOptions;
 	}
 
@@ -7276,7 +7276,7 @@
 }
 public void testBug565388_001() {
 	if (this.complianceLevel < ClassFileConstants.JDK17) return;
-	Map<String, String> options = getCompilerOptionsWithPreview();
+	Map<String, String> options = getCompilerOptionsWithPreviewIfApplicable();
 	this.runNegativeTest(
 		new String[] {
 			"X.java",
@@ -7296,7 +7296,7 @@
 }
 public void testBug565388_002() {
 	if (this.complianceLevel < ClassFileConstants.JDK17) return;
-	Map<String, String> options = getCompilerOptionsWithPreview();
+	Map<String, String> options = getCompilerOptionsWithPreviewIfApplicable();
 	this.runNegativeTest(
 		new String[] {
 			"X.java",
@@ -7758,7 +7758,7 @@
 	}
 public void testBug566063_001() {
 	if (this.complianceLevel < ClassFileConstants.JDK17) return;
-	Map<String, String> options = getCompilerOptionsWithPreview();
+	Map<String, String> options = getCompilerOptionsWithPreviewIfApplicable();
 	runConformTest(
 			new String[] {
 				"X.java",
@@ -7785,7 +7785,7 @@
 }
 public void testBug566063_002() {
 	if (this.complianceLevel < ClassFileConstants.JDK17) return;
-	Map<String, String> options = getCompilerOptionsWithPreview();
+	Map<String, String> options = getCompilerOptionsWithPreviewIfApplicable();
 	runNegativeTest(
 			new String[] {
 				"X.java",
@@ -7819,7 +7819,7 @@
 }
 public void testBug566063_003() {
 	if (this.complianceLevel < ClassFileConstants.JDK17) return;
-	Map<String, String> options = getCompilerOptionsWithPreview();
+	Map<String, String> options = getCompilerOptionsWithPreviewIfApplicable();
 	runNegativeTest(
 			new String[] {
 				"X.java",
@@ -8041,7 +8041,7 @@
 }
 public void testBug567731_001() {
 	if (this.complianceLevel < ClassFileConstants.JDK17) return;
-	Map<String, String> options = getCompilerOptionsWithPreview();
+	Map<String, String> options = getCompilerOptionsWithPreviewIfApplicable();
 	this.runNegativeTest(
 		new String[] {
 			"X.java",
@@ -8071,7 +8071,7 @@
 }
 public void testBug567731_002() {
 	if (this.complianceLevel < ClassFileConstants.JDK17) return;
-	Map<String, String> options = getCompilerOptionsWithPreview();
+	Map<String, String> options = getCompilerOptionsWithPreviewIfApplicable();
 	this.runNegativeTest(
 		new String[] {
 			"X.java",
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SealedTypesTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SealedTypesTests.java
index ffc9d7e..86dddc0 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SealedTypesTests.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SealedTypesTests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2020, 2021 IBM Corporation and others.
+ * Copyright (c) 2020, 2022 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
@@ -31,7 +31,7 @@
 	static {
 //		TESTS_NUMBERS = new int [] { 40 };
 //		TESTS_RANGE = new int[] { 1, -1 };
-//		TESTS_NAMES = new String[] { "testBug573450"};
+//		TESTS_NAMES = new String[] { "testBug564638_056"};
 	}
 
 	public static Class<?> testClass() {
@@ -1378,7 +1378,7 @@
 				},
 				lib1Path,
 				JavaCore.VERSION_17,
-				true);
+				false);
 		String[] libs = getDefaultClassPaths();
 		int len = libs.length;
 		System.arraycopy(libs, 0, libs = new String[len+1], 0, len);
@@ -1688,7 +1688,7 @@
 			"1. ERROR in X.java (at line 1)\n" +
 			"	class permits {\n" +
 			"	      ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 3)\n" +
 			"	Zork();\n" +
@@ -1714,7 +1714,7 @@
 			"1. ERROR in X.java (at line 1)\n" +
 			"	class permits {\n" +
 			"	      ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 3)\n" +
 			"	Zork();\n" +
@@ -1744,7 +1744,7 @@
 			"1. ERROR in X.java (at line 2)\n" +
 			"	permits p;\n" +
 			"	^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 4)\n" +
 			"	Zork();\n" +
@@ -1755,7 +1755,7 @@
 			"1. ERROR in permits.java (at line 1)\n" +
 			"	public class permits {\n" +
 			"	             ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -1780,7 +1780,7 @@
 			"1. ERROR in X.java (at line 2)\n" +
 			"	permits p;\n" +
 			"	^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 4)\n" +
 			"	Zork();\n" +
@@ -1791,7 +1791,7 @@
 			"1. ERROR in permits.java (at line 1)\n" +
 			"	public class permits {\n" +
 			"	             ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -1811,7 +1811,7 @@
 			"1. ERROR in X.java (at line 1)\n" +
 			"	class X<permits> {\n" +
 			"	        ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 3)\n" +
 			"	Zork();\n" +
@@ -1837,7 +1837,7 @@
 			"1. ERROR in X.java (at line 1)\n" +
 			"	class X<permits> {\n" +
 			"	        ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 3)\n" +
 			"	Zork();\n" +
@@ -1861,7 +1861,7 @@
 			"1. ERROR in X.java (at line 1)\n" +
 			"	class X extends permits {\n" +
 			"	                ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 3)\n" +
 			"	Zork();\n" +
@@ -1871,7 +1871,7 @@
 			"3. ERROR in X.java (at line 6)\n" +
 			"	class permits {\n" +
 			"	      ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -1893,7 +1893,7 @@
 			"1. ERROR in X.java (at line 1)\n" +
 			"	class X extends permits {\n" +
 			"	                ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 3)\n" +
 			"	Zork();\n" +
@@ -1903,7 +1903,7 @@
 			"3. ERROR in X.java (at line 6)\n" +
 			"	class permits {\n" +
 			"	      ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -1926,7 +1926,7 @@
 			"1. ERROR in X.java (at line 1)\n" +
 			"	class X implements permits {\n" +
 			"	                   ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 3)\n" +
 			"	Zork();\n" +
@@ -1936,7 +1936,7 @@
 			"3. ERROR in X.java (at line 6)\n" +
 			"	interface permits {\n" +
 			"	          ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -1958,7 +1958,7 @@
 			"1. ERROR in X.java (at line 1)\n" +
 			"	class X implements permits {\n" +
 			"	                   ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 3)\n" +
 			"	Zork();\n" +
@@ -1968,7 +1968,7 @@
 			"3. ERROR in X.java (at line 6)\n" +
 			"	interface permits {\n" +
 			"	          ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -1991,7 +1991,7 @@
 			"1. ERROR in X.java (at line 1)\n" +
 			"	interface X extends permits {\n" +
 			"	                    ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 3)\n" +
 			"	Zork();\n" +
@@ -2001,7 +2001,7 @@
 			"3. ERROR in X.java (at line 6)\n" +
 			"	interface permits {\n" +
 			"	          ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -2023,7 +2023,7 @@
 			"1. ERROR in X.java (at line 1)\n" +
 			"	interface X extends permits {\n" +
 			"	                    ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 3)\n" +
 			"	Zork();\n" +
@@ -2033,7 +2033,7 @@
 			"3. ERROR in X.java (at line 6)\n" +
 			"	interface permits {\n" +
 			"	          ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -2060,7 +2060,7 @@
 			"2. ERROR in X.java (at line 2)\n" +
 			"	permits foo() {\n" +
 			"	^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"3. ERROR in X.java (at line 3)\n" +
 			"	Zork();\n" +
@@ -2086,7 +2086,7 @@
 			"1. ERROR in X.java (at line 2)\n" +
 			"	permits foo() {\n" +
 			"	^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"3. ERROR in X.java (at line 3)\n" +
 			"	Zork();\n" +
@@ -2112,7 +2112,7 @@
 			"1. ERROR in X.java (at line 2)\n" +
 			"	void foo() throws permits{\n" +
 			"	                  ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 3)\n" +
 			"	Zork();\n" +
@@ -2137,7 +2137,7 @@
 			"1. ERROR in X.java (at line 2)\n" +
 			"	void foo() throws permits{\n" +
 			"	                  ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"3. ERROR in X.java (at line 3)\n" +
 			"	Zork();\n" +
@@ -2163,7 +2163,7 @@
 			"1. ERROR in X.java (at line 1)\n" +
 			"	class X <T extends permits> {\n" +
 			"	                   ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 1)\n" +
 			"	class X <T extends permits> {\n" +
@@ -2203,7 +2203,7 @@
 			"1. ERROR in X.java (at line 1)\n" +
 			"	class X <T extends permits>{\n" +
 			"	                   ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"3. ERROR in X.java (at line 1)\n" +
 			"	class X <T extends permits>{\n" +
@@ -2246,7 +2246,7 @@
 			"1. ERROR in X.java (at line 3)\n" +
 			"	private final permits p;\n" +
 			"	              ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 5)\n" +
 			"	Zork();\n" +
@@ -2273,7 +2273,7 @@
 			"1. ERROR in X.java (at line 3)\n" +
 			"	private final permits p;\n" +
 			"	              ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"3. ERROR in X.java (at line 5)\n" +
 			"	Zork();\n" +
@@ -2308,7 +2308,7 @@
 			"2. ERROR in X.java (at line 3)\n" +
 			"	I i = (permits p)-> {};\n" +
 			"	       ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -2337,7 +2337,7 @@
 			"2. ERROR in X.java (at line 3)\n" +
 			"	I i = (permits p)-> {};\n" +
 			"	       ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"4. ERROR in X.java (at line 4)\n" +
 			"	Zork();\n" +
@@ -2361,7 +2361,7 @@
 			"1. ERROR in X.java (at line 2)\n" +
 			"	public void foo(permits this) {}\n" +
 			"	                ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -2379,7 +2379,7 @@
 			"1. ERROR in X.java (at line 2)\n" +
 			"	public void foo(permits this) {}\n" +
 			"	                ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -2398,7 +2398,7 @@
 			"1. ERROR in X.java (at line 2)\n" +
 			"	public void foo(permits this) {}\n" +
 			"	                ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -2416,7 +2416,7 @@
 			"1. ERROR in X.java (at line 2)\n" +
 			"	public void foo(permits this) {}\n" +
 			"	                ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -2437,12 +2437,12 @@
 			"1. ERROR in X.java (at line 2)\n" +
 			"	class permits {\n" +
 			"	      ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 3)\n" +
 			"	public void foo(permits this) {}\n" +
 			"	                ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -2462,12 +2462,12 @@
 			"1. ERROR in X.java (at line 2)\n" +
 			"	class permits {\n" +
 			"	      ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 3)\n" +
 			"	public void foo(permits this) {}\n" +
 			"	                ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -2489,7 +2489,7 @@
 			"1. ERROR in X.java (at line 3)\n" +
 			"	permits p;\n" +
 			"	^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 4)\n" +
 			"	Zork();\n" +
@@ -2515,7 +2515,7 @@
 			"1. ERROR in X.java (at line 3)\n" +
 			"	permits p;\n" +
 			"	^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"3. ERROR in X.java (at line 4)\n" +
 			"	Zork();\n" +
@@ -2544,7 +2544,7 @@
 			"1. ERROR in X.java (at line 3)\n" +
 			"	for (permits i = 0; i < 10; ++i) {} \n" +
 			"	     ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 6)\n" +
 			"	Zork();\n" +
@@ -2572,7 +2572,7 @@
 			"1. ERROR in X.java (at line 3)\n" +
 			"	for (permits i = 0; i < 10; ++i) {} \n" +
 			"	     ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"3. ERROR in X.java (at line 6)\n" +
 			"	Zork();\n" +
@@ -2598,12 +2598,12 @@
 			"1. ERROR in X.java (at line 2)\n" +
 			"	public static void main(permits[] args) {\n" +
 			"	                        ^^^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 3)\n" +
 			"	for (permits p : args) {} \n" +
 			"	     ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -2623,12 +2623,12 @@
 			"1. ERROR in X.java (at line 2)\n" +
 			"	public static void main(permits[] args) {\n" +
 			"	                        ^^^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"3. ERROR in X.java (at line 3)\n" +
 			"	for (permits p : args) {} \n" +
 			"	     ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -2659,7 +2659,7 @@
 			"1. ERROR in X.java (at line 3)\n" +
 			"	try (permits y = new Y()) {\n" +
 			"	     ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -2689,7 +2689,7 @@
 			"1. ERROR in X.java (at line 3)\n" +
 			"	try (permits y = new Y()) {\n" +
 			"	     ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -2720,7 +2720,7 @@
 			"1. ERROR in X.java (at line 5)\n" +
 			"	} catch (permits e) {\n" +
 			"	         ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -2750,7 +2750,7 @@
 			"1. ERROR in X.java (at line 5)\n" +
 			"	} catch (permits e) {\n" +
 			"	         ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -2773,7 +2773,7 @@
 			"2. ERROR in X.java (at line 1)\n" +
 			"	record X(permits p) {\n" +
 			"	         ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -2818,7 +2818,7 @@
 			"1. ERROR in X.java (at line 5)\n" +
 			"	<permits>this(t);\n" +
 			"	 ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 5)\n" +
 			"	<permits>this(t);\n" +
@@ -2845,7 +2845,7 @@
 			"1. ERROR in X.java (at line 5)\n" +
 			"	<permits>this(t);\n" +
 			"	 ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"3. ERROR in X.java (at line 5)\n" +
 			"	<permits>this(t);\n" +
@@ -2879,7 +2879,7 @@
 			"2. ERROR in X.java (at line 5)\n" +
 			"	new <permits>X(t).foo();\n" +
 			"	     ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -2907,7 +2907,7 @@
 			"2. ERROR in X.java (at line 5)\n" +
 			"	new <permits>X(t).foo();\n" +
 			"	     ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -2931,7 +2931,7 @@
 			"1. ERROR in X.java (at line 6)\n" +
 			"	x.<permits>foo(0);\n" +
 			"	   ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 6)\n" +
 			"	x.<permits>foo(0);\n" +
@@ -2959,7 +2959,7 @@
 			"1. ERROR in X.java (at line 6)\n" +
 			"	x.<permits>foo(0);\n" +
 			"	   ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"3. ERROR in X.java (at line 6)\n" +
 			"	x.<permits>foo(0);\n" +
@@ -2987,7 +2987,7 @@
 			"1. ERROR in X.java (at line 5)\n" +
 			"	X x = new permits();\n" +
 			"	          ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -3009,7 +3009,7 @@
 			"1. ERROR in X.java (at line 5)\n" +
 			"	X x = new permits();\n" +
 			"	          ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -3036,12 +3036,12 @@
 			"1. ERROR in X.java (at line 3)\n" +
 			"	new permits() {\n" +
 			"	    ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 9)\n" +
 			"	abstract class permits {\n" +
 			"	               ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -3069,7 +3069,7 @@
 			"1. ERROR in X.java (at line 3)\n" +
 			"	new permits() {\n" +
 			"	    ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 6)\n" +
 			"	Zork();\n" +
@@ -3079,7 +3079,7 @@
 			"3. ERROR in X.java (at line 11)\n" +
 			"	abstract class permits {\n" +
 			"	               ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -3100,7 +3100,7 @@
 			"1. ERROR in X.java (at line 3)\n" +
 			"	Object[] p = new permits[10];\n" +
 			"	                 ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -3120,7 +3120,7 @@
 			"1. ERROR in X.java (at line 3)\n" +
 			"	Object[] p = new permits[10];\n" +
 			"	                 ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -3147,12 +3147,12 @@
 			"2. ERROR in X.java (at line 3)\n" +
 			"	new X().foo((permits) null);\n" +
 			"	             ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"3. ERROR in X.java (at line 5)\n" +
 			"	private void foo(permits o) {}\n" +
 			"	                 ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -3178,12 +3178,12 @@
 			"2. ERROR in X.java (at line 3)\n" +
 			"	new X().foo((permits) null);\n" +
 			"	             ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"4. ERROR in X.java (at line 5)\n" +
 			"	private void foo(permits o) {}\n" +
 			"	                 ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -3204,7 +3204,7 @@
 			"1. ERROR in X.java (at line 3)\n" +
 			"	if (o instanceof permits) {}\n" +
 			"	                 ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -3224,7 +3224,7 @@
 			"1. ERROR in X.java (at line 3)\n" +
 			"	if (o instanceof permits) {}\n" +
 			"	                 ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -3256,7 +3256,7 @@
 			"2. ERROR in X.java (at line 8)\n" +
 			"	class permits{}\n" +
 			"	      ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -3287,7 +3287,7 @@
 			"2. ERROR in X.java (at line 8)\n" +
 			"	class permits{}\n" +
 			"	      ^^^^^^^\n" +
-			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'permits\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -3311,7 +3311,7 @@
 			"1. ERROR in X.java (at line 1)\n" +
 			"	class sealed {\n" +
 			"	      ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 3)\n" +
 			"	Zork();\n" +
@@ -3337,7 +3337,7 @@
 			"1. ERROR in X.java (at line 1)\n" +
 			"	class sealed {\n" +
 			"	      ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 3)\n" +
 			"	Zork();\n" +
@@ -3367,7 +3367,7 @@
 			"1. ERROR in X.java (at line 2)\n" +
 			"	sealed p;\n" +
 			"	^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 4)\n" +
 			"	Zork();\n" +
@@ -3378,7 +3378,7 @@
 			"1. ERROR in sealed.java (at line 1)\n" +
 			"	public class sealed {\n" +
 			"	             ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -3403,7 +3403,7 @@
 			"1. ERROR in X.java (at line 2)\n" +
 			"	sealed p;\n" +
 			"	^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 4)\n" +
 			"	Zork();\n" +
@@ -3414,7 +3414,7 @@
 			"1. ERROR in sealed.java (at line 1)\n" +
 			"	public class sealed {\n" +
 			"	             ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -3434,7 +3434,7 @@
 			"1. ERROR in X.java (at line 1)\n" +
 			"	class X<sealed> {\n" +
 			"	        ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 3)\n" +
 			"	Zork();\n" +
@@ -3460,7 +3460,7 @@
 			"1. ERROR in X.java (at line 1)\n" +
 			"	class X<sealed> {\n" +
 			"	        ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 3)\n" +
 			"	Zork();\n" +
@@ -3484,7 +3484,7 @@
 			"1. ERROR in X.java (at line 1)\n" +
 			"	class X extends sealed {\n" +
 			"	                ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 3)\n" +
 			"	Zork();\n" +
@@ -3494,7 +3494,7 @@
 			"3. ERROR in X.java (at line 6)\n" +
 			"	class sealed {\n" +
 			"	      ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -3516,7 +3516,7 @@
 			"1. ERROR in X.java (at line 1)\n" +
 			"	class X extends sealed {\n" +
 			"	                ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 3)\n" +
 			"	Zork();\n" +
@@ -3526,7 +3526,7 @@
 			"3. ERROR in X.java (at line 6)\n" +
 			"	class sealed {\n" +
 			"	      ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -3549,7 +3549,7 @@
 			"1. ERROR in X.java (at line 1)\n" +
 			"	class X implements sealed {\n" +
 			"	                   ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 3)\n" +
 			"	Zork();\n" +
@@ -3559,7 +3559,7 @@
 			"3. ERROR in X.java (at line 6)\n" +
 			"	interface sealed {\n" +
 			"	          ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -3581,7 +3581,7 @@
 			"1. ERROR in X.java (at line 1)\n" +
 			"	class X implements sealed {\n" +
 			"	                   ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 3)\n" +
 			"	Zork();\n" +
@@ -3591,7 +3591,7 @@
 			"3. ERROR in X.java (at line 6)\n" +
 			"	interface sealed {\n" +
 			"	          ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -3614,7 +3614,7 @@
 			"1. ERROR in X.java (at line 1)\n" +
 			"	interface X extends sealed {\n" +
 			"	                    ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 3)\n" +
 			"	Zork();\n" +
@@ -3624,7 +3624,7 @@
 			"3. ERROR in X.java (at line 6)\n" +
 			"	interface sealed {\n" +
 			"	          ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -3646,7 +3646,7 @@
 			"1. ERROR in X.java (at line 1)\n" +
 			"	interface X extends sealed {\n" +
 			"	                    ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 3)\n" +
 			"	Zork();\n" +
@@ -3656,7 +3656,7 @@
 			"3. ERROR in X.java (at line 6)\n" +
 			"	interface sealed {\n" +
 			"	          ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -3683,7 +3683,7 @@
 			"2. ERROR in X.java (at line 2)\n" +
 			"	sealed foo() {\n" +
 			"	^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"3. ERROR in X.java (at line 3)\n" +
 			"	Zork();\n" +
@@ -3709,7 +3709,7 @@
 			"1. ERROR in X.java (at line 2)\n" +
 			"	sealed foo() {\n" +
 			"	^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"3. ERROR in X.java (at line 3)\n" +
 			"	Zork();\n" +
@@ -3735,7 +3735,7 @@
 			"1. ERROR in X.java (at line 2)\n" +
 			"	void foo() throws sealed{\n" +
 			"	                  ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 3)\n" +
 			"	Zork();\n" +
@@ -3760,7 +3760,7 @@
 			"1. ERROR in X.java (at line 2)\n" +
 			"	void foo() throws sealed{\n" +
 			"	                  ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"3. ERROR in X.java (at line 3)\n" +
 			"	Zork();\n" +
@@ -3786,7 +3786,7 @@
 			"1. ERROR in X.java (at line 1)\n" +
 			"	class X <T extends sealed> {\n" +
 			"	                   ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 1)\n" +
 			"	class X <T extends sealed> {\n" +
@@ -3826,7 +3826,7 @@
 			"1. ERROR in X.java (at line 1)\n" +
 			"	class X <T extends sealed>{\n" +
 			"	                   ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"3. ERROR in X.java (at line 1)\n" +
 			"	class X <T extends sealed>{\n" +
@@ -3869,7 +3869,7 @@
 			"1. ERROR in X.java (at line 3)\n" +
 			"	private final sealed p;\n" +
 			"	              ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 5)\n" +
 			"	Zork();\n" +
@@ -3896,7 +3896,7 @@
 			"1. ERROR in X.java (at line 3)\n" +
 			"	private final sealed p;\n" +
 			"	              ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"3. ERROR in X.java (at line 5)\n" +
 			"	Zork();\n" +
@@ -3931,7 +3931,7 @@
 			"2. ERROR in X.java (at line 3)\n" +
 			"	I i = (sealed p)-> {};\n" +
 			"	       ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -3960,7 +3960,7 @@
 			"2. ERROR in X.java (at line 3)\n" +
 			"	I i = (sealed p)-> {};\n" +
 			"	       ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"4. ERROR in X.java (at line 4)\n" +
 			"	Zork();\n" +
@@ -3984,7 +3984,7 @@
 			"1. ERROR in X.java (at line 2)\n" +
 			"	public void foo(sealed this) {}\n" +
 			"	                ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -4002,7 +4002,7 @@
 			"1. ERROR in X.java (at line 2)\n" +
 			"	public void foo(sealed this) {}\n" +
 			"	                ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -4021,7 +4021,7 @@
 			"1. ERROR in X.java (at line 2)\n" +
 			"	public void foo(sealed this) {}\n" +
 			"	                ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -4039,7 +4039,7 @@
 			"1. ERROR in X.java (at line 2)\n" +
 			"	public void foo(sealed this) {}\n" +
 			"	                ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -4060,12 +4060,12 @@
 			"1. ERROR in X.java (at line 2)\n" +
 			"	class sealed {\n" +
 			"	      ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 3)\n" +
 			"	public void foo(sealed this) {}\n" +
 			"	                ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -4085,12 +4085,12 @@
 			"1. ERROR in X.java (at line 2)\n" +
 			"	class sealed {\n" +
 			"	      ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 3)\n" +
 			"	public void foo(sealed this) {}\n" +
 			"	                ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -4112,7 +4112,7 @@
 			"1. ERROR in X.java (at line 3)\n" +
 			"	sealed p;\n" +
 			"	^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 4)\n" +
 			"	Zork();\n" +
@@ -4138,7 +4138,7 @@
 			"1. ERROR in X.java (at line 3)\n" +
 			"	sealed p;\n" +
 			"	^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"3. ERROR in X.java (at line 4)\n" +
 			"	Zork();\n" +
@@ -4167,7 +4167,7 @@
 			"1. ERROR in X.java (at line 3)\n" +
 			"	for (sealed i = 0; i < 10; ++i) {} \n" +
 			"	     ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 6)\n" +
 			"	Zork();\n" +
@@ -4195,7 +4195,7 @@
 			"1. ERROR in X.java (at line 3)\n" +
 			"	for (sealed i = 0; i < 10; ++i) {} \n" +
 			"	     ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"3. ERROR in X.java (at line 6)\n" +
 			"	Zork();\n" +
@@ -4221,12 +4221,12 @@
 			"1. ERROR in X.java (at line 2)\n" +
 			"	public static void main(sealed[] args) {\n" +
 			"	                        ^^^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 3)\n" +
 			"	for (sealed p : args) {} \n" +
 			"	     ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -4246,12 +4246,12 @@
 			"1. ERROR in X.java (at line 2)\n" +
 			"	public static void main(sealed[] args) {\n" +
 			"	                        ^^^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"3. ERROR in X.java (at line 3)\n" +
 			"	for (sealed p : args) {} \n" +
 			"	     ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -4282,7 +4282,7 @@
 			"1. ERROR in X.java (at line 3)\n" +
 			"	try (sealed y = new Y()) {\n" +
 			"	     ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -4312,7 +4312,7 @@
 			"1. ERROR in X.java (at line 3)\n" +
 			"	try (sealed y = new Y()) {\n" +
 			"	     ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -4343,7 +4343,7 @@
 			"1. ERROR in X.java (at line 5)\n" +
 			"	} catch (sealed e) {\n" +
 			"	         ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -4373,7 +4373,7 @@
 			"1. ERROR in X.java (at line 5)\n" +
 			"	} catch (sealed e) {\n" +
 			"	         ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -4396,7 +4396,7 @@
 			"2. ERROR in X.java (at line 1)\n" +
 			"	record X(sealed p) {\n" +
 			"	         ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -4441,7 +4441,7 @@
 			"1. ERROR in X.java (at line 5)\n" +
 			"	<sealed>this(t);\n" +
 			"	 ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 5)\n" +
 			"	<sealed>this(t);\n" +
@@ -4468,7 +4468,7 @@
 			"1. ERROR in X.java (at line 5)\n" +
 			"	<sealed>this(t);\n" +
 			"	 ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"3. ERROR in X.java (at line 5)\n" +
 			"	<sealed>this(t);\n" +
@@ -4502,7 +4502,7 @@
 			"2. ERROR in X.java (at line 5)\n" +
 			"	new <sealed>X(t).foo();\n" +
 			"	     ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -4530,7 +4530,7 @@
 			"2. ERROR in X.java (at line 5)\n" +
 			"	new <sealed>X(t).foo();\n" +
 			"	     ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -4554,7 +4554,7 @@
 			"1. ERROR in X.java (at line 6)\n" +
 			"	x.<sealed>foo(0);\n" +
 			"	   ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 6)\n" +
 			"	x.<sealed>foo(0);\n" +
@@ -4582,7 +4582,7 @@
 			"1. ERROR in X.java (at line 6)\n" +
 			"	x.<sealed>foo(0);\n" +
 			"	   ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"3. ERROR in X.java (at line 6)\n" +
 			"	x.<sealed>foo(0);\n" +
@@ -4610,7 +4610,7 @@
 			"1. ERROR in X.java (at line 5)\n" +
 			"	X x = new sealed();\n" +
 			"	          ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -4632,7 +4632,7 @@
 			"1. ERROR in X.java (at line 5)\n" +
 			"	X x = new sealed();\n" +
 			"	          ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -4659,12 +4659,12 @@
 			"1. ERROR in X.java (at line 3)\n" +
 			"	new sealed() {\n" +
 			"	    ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 9)\n" +
 			"	abstract class sealed {\n" +
 			"	               ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -4692,7 +4692,7 @@
 			"1. ERROR in X.java (at line 3)\n" +
 			"	new sealed() {\n" +
 			"	    ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"2. ERROR in X.java (at line 6)\n" +
 			"	Zork();\n" +
@@ -4702,7 +4702,7 @@
 			"3. ERROR in X.java (at line 11)\n" +
 			"	abstract class sealed {\n" +
 			"	               ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -4723,7 +4723,7 @@
 			"1. ERROR in X.java (at line 3)\n" +
 			"	Object[] p = new sealed[10];\n" +
 			"	                 ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -4743,7 +4743,7 @@
 			"1. ERROR in X.java (at line 3)\n" +
 			"	Object[] p = new sealed[10];\n" +
 			"	                 ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -4770,12 +4770,12 @@
 			"2. ERROR in X.java (at line 3)\n" +
 			"	new X().foo((sealed) null);\n" +
 			"	             ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"3. ERROR in X.java (at line 5)\n" +
 			"	private void foo(sealed o) {}\n" +
 			"	                 ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -4801,12 +4801,12 @@
 			"2. ERROR in X.java (at line 3)\n" +
 			"	new X().foo((sealed) null);\n" +
 			"	             ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n" +
 			"4. ERROR in X.java (at line 5)\n" +
 			"	private void foo(sealed o) {}\n" +
 			"	                 ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -4827,7 +4827,7 @@
 			"1. ERROR in X.java (at line 3)\n" +
 			"	if (o instanceof sealed) {}\n" +
 			"	                 ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -4847,7 +4847,7 @@
 			"1. ERROR in X.java (at line 3)\n" +
 			"	if (o instanceof sealed) {}\n" +
 			"	                 ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -4879,7 +4879,7 @@
 			"2. ERROR in X.java (at line 8)\n" +
 			"	class sealed{}\n" +
 			"	      ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n");
 	}
 	@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -4910,7 +4910,7 @@
 			"2. ERROR in X.java (at line 8)\n" +
 			"	class sealed{}\n" +
 			"	      ^^^^^^\n" +
-			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java "+ AbstractRegressionTest.PREVIEW_ALLOWED_LEVEL +"\n" +
+			"\'sealed\' is not a valid type name; it is a restricted identifier and not allowed as a type identifier in Java 17\n" +
 			"----------\n",
 			null,
 			true,
@@ -5722,4 +5722,44 @@
 				+ "The type Y extending a sealed class X should be a permitted subtype of X\n"
 				+ "----------\n");
 	}
+	public void testBug578619_1() {
+		runConformTest(
+				new String[] {
+						"Bug578619.java",
+						"public class Bug578619 {\n"
+						+ "	public static void main(String[] args) {\n"
+						+ "		System.out.println(\"Hola\");\n"
+						+ "	}\n"
+						+ "}\n"
+						+ "sealed interface I1 permits I2, I3 {}\n"
+						+ "non-sealed interface I2 extends I1 {}\n"
+						+ "non-sealed interface I3 extends I2, I1 {}"
+				},
+				"Hola");
+	}
+	public void testBug578619_2() {
+		runNegativeTest(
+				new String[] {
+						"Bug578619.java",
+						"public class Bug578619 {\n"
+						+ "	public static void main(String[] args) {\n"
+						+ "		System.out.println(\"Hola\");\n"
+						+ "	}\n"
+						+ "}\n"
+						+ "sealed interface I1 permits I2, I3 {}\n"
+						+ "non-sealed interface I2 extends I1 {}\n"
+						+ "non-sealed interface I3 extends I2 {}"
+				},
+				"----------\n" +
+				"1. ERROR in Bug578619.java (at line 6)\n" +
+				"	sealed interface I1 permits I2, I3 {}\n" +
+				"	                                ^^\n" +
+				"Permitted type I3 does not declare I1 as direct super interface \n" +
+				"----------\n" +
+				"2. ERROR in Bug578619.java (at line 8)\n" +
+				"	non-sealed interface I3 extends I2 {}\n" +
+				"	                     ^^\n" +
+				"An interface I3 declared as non-sealed should have a sealed direct superinterface\n" +
+				"----------\n");
+	}
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchPatternTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchPatternTest.java
index d35f62f..326de6a 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchPatternTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchPatternTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2021 IBM Corporation and others.
+ * Copyright (c) 2021, 2022 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
@@ -29,16 +29,16 @@
 	static {
 //		TESTS_NUMBERS = new int [] { 40 };
 //		TESTS_RANGE = new int[] { 1, -1 };
-//		TESTS_NAMES = new String[] { "testBug575737"};
+//		TESTS_NAMES = new String[] { "testBug579355"};
 	}
 
-	private static String previewLevel = "17";
+	private static String previewLevel = "18";
 
 	public static Class<?> testClass() {
 		return SwitchPatternTest.class;
 	}
 	public static Test suite() {
-		return buildMinimalComplianceTestSuite(testClass(), F_17);
+		return buildMinimalComplianceTestSuite(testClass(), F_18);
 	}
 	public SwitchPatternTest(String testName){
 		super(testName);
@@ -47,9 +47,9 @@
 	// Enables the tests to run individually
 	protected Map<String, String> getCompilerOptions() {
 		Map<String, String> defaultOptions = super.getCompilerOptions();
-		defaultOptions.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_17); // FIXME
-		defaultOptions.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_17);
-		defaultOptions.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_17);
+		defaultOptions.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_18);
+		defaultOptions.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_18);
+		defaultOptions.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_18);
 		defaultOptions.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
 		defaultOptions.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
 		defaultOptions.put(CompilerOptions.OPTION_Store_Annotations, CompilerOptions.ENABLED);
@@ -3510,20 +3510,20 @@
 					"public class X {\n"+
 					"	static String foo(Color o) {\n" +
 					"		return switch (o) {\n" +
-					"	     case Red -> \"Red\";\n" +
+					"	     case Red -> \"Const:Red\";\n" +
 					"	     case Color s -> s.toString();\n" +
 					"	   };\n" +
 					"	}\n" +
 					"	public static void main(String[] args) {\n" +
-					"		System.out.println(Color.Red);\n" +
-					"		System.out.println(Color.Blue);\n" +
+					"		System.out.println(foo(Color.Red));\n" +
+					"		System.out.println(foo(Color.Blue));\n" +
 					"	}\n" +
 					"} \n" +
 					"enum Color {\n" +
 					"	Blue, Red; \n" +
 					"}",
 				},
-				"Red\n" +
+				"Const:Red\n" +
 				"Blue");
 	}
 	public void testBug575047_12() {
@@ -3534,7 +3534,7 @@
 					"	static String foo(Color o) {\n" +
 					"		return switch (o) {\n" +
 					"	     case Red -> \"Red\";\n" +
-					"	     case Color s && s == Color.Blue  -> s.toString();" +
+					"	     case Color s && s == Color.Blue  -> s.toString();\n" +
 					"	     case Color s -> s.toString();\n" +
 					"	   };\n" +
 					"	}\n" +
@@ -3557,7 +3557,7 @@
 					"public class X {\n"+
 					"	static String foo(Color o) {\n" +
 					"		return switch (o) {\n" +
-					"	     case Color s && s == Color.Blue  -> s.toString();" +
+					"	     case Color s && s == Color.Blue  -> s.toString();\n" +
 					"	     case Red -> \"Red\";\n" +
 					"	     case null -> \"\";\n" +
 					"	   };\n" +
@@ -3572,6 +3572,11 @@
 				"	return switch (o) {\n" +
 				"	               ^\n" +
 				"A Switch expression should cover all possible values\n" +
+				"----------\n" +
+				"2. ERROR in X.java (at line 5)\n" +
+				"	case Red -> \"Red\";\n" +
+				"	     ^^^\n" +
+				"This case label is dominated by one of the preceding case label\n" +
 				"----------\n");
 	}
 	public void testBug575047_14() {
@@ -3581,7 +3586,7 @@
 					"public class X {\n"+
 					"	static String foo(Color o) {\n" +
 					"		return switch (o) {\n" +
-					"	     case Color s && s == Color.Blue  -> s.toString();" +
+					"	     case Color s && s == Color.Blue  -> s.toString();\n" +
 					"	     case Red -> \"Red\";\n" +
 					"	   };\n" +
 					"	}\n" +
@@ -3595,6 +3600,11 @@
 				"	return switch (o) {\n" +
 				"	               ^\n" +
 				"A Switch expression should cover all possible values\n" +
+				"----------\n" +
+				"2. ERROR in X.java (at line 5)\n" +
+				"	case Red -> \"Red\";\n" +
+				"	     ^^^\n" +
+				"This case label is dominated by one of the preceding case label\n" +
 				"----------\n");
 	}
 	public void testBug575047_15() {
@@ -4101,5 +4111,1178 @@
 				"		#102 REF_getField c:Lp/Rec$MyInterface;";
 		SwitchPatternTest.verifyClassFile(expectedOutput, "p/Rec.class", ClassFileBytesDisassembler.SYSTEM);
 	}
-
+	public void testBug576785_001() {
+		runConformTest(
+			new String[] {
+				"X.java",
+				"sealed interface J<X> permits D, E {}\n"+
+				"final class D implements J<String> {}\n"+
+				"final class E<X> implements J<X> {}\n"+
+				"\n"+
+				"public class X {\n"+
+				"       static int testExhaustive2(J<Integer> ji) {\n"+
+				"               return switch (ji) { // Exhaustive!\n"+
+				"               case E<Integer> e -> 42;\n"+
+				"               };\n"+
+				"       }\n"+
+				"       public static void main(String[] args) {\n"+
+				"               J<Integer> ji = new E<>();\n"+
+				"               System.out.println(X.testExhaustive2(ji));\n"+
+				"       }\n"+
+				"}",
+			},
+			"42");
+	}
+	public void testBug576785_002() {
+		runNegativeTest(
+				new String[] {
+				"X.java",
+				"@SuppressWarnings(\"rawtypes\")\n" +
+				"sealed interface J<T> permits D, E, F {}\n"+
+				"final class D implements J<String> {}\n"+
+				"final class E<T> implements J<T> {}\n"+
+				"final class F<T> implements J<T> {}\n"+
+				"\n"+
+				"public class X {\n"+
+				"@SuppressWarnings(\"preview\")\n" +
+				" static int testExhaustive2(J<Integer> ji) {\n"+
+				"   return switch (ji) { // Exhaustive!\n"+
+				"   case E<Integer> e -> 42;\n"+
+				"   };\n"+
+				" }\n"+
+				" public static void main(String[] args) {\n"+
+				"   J<Integer> ji = new E<>();\n"+
+				"   System.out.println(X.testExhaustive2(ji));\n"+
+				"   Zork();\n"+
+				" }\n"+
+				"}"
+				},
+				"----------\n" +
+				"1. ERROR in X.java (at line 10)\n" +
+				"	return switch (ji) { // Exhaustive!\n" +
+				"	               ^^\n" +
+				"A switch expression should have a default case\n" +
+				"----------\n" +
+				"2. ERROR in X.java (at line 17)\n" +
+				"	Zork();\n" +
+				"	^^^^\n" +
+				"The method Zork() is undefined for the type X\n" +
+				"----------\n");
+	}
+	public void testBug576830_001() {
+		runNegativeTest(
+			new String[] {
+				"X.java",
+				"public class X {\n"+
+				" static void foo(Object o) {\n"+
+				"   switch (o) {\n"+
+				"   };\n"+
+				" }\n"+
+				" public static void main(String[] args) {\n"+
+				"   foo(\"Hello\");\n"+
+				" }\n"+
+				"}",
+			},
+			"----------\n" +
+			"1. ERROR in X.java (at line 3)\n" +
+			"	switch (o) {\n" +
+			"	        ^\n" +
+			"An enhanced switch statement should be exhaustive; a default label expected\n" +
+			"----------\n");
+	}
+	public void testBug578107_001() {
+		runNegativeTest(
+			new String[] {
+				"X.java",
+				"sealed class C permits D {}\n"+
+				"final class D extends C {}\n"+
+				"public class X {\n"+
+				"       @SuppressWarnings(\"preview\")\n"+
+				"       static  void foo(C ji) {\n"+
+				"                switch (ji) { // non-exhaustive\n"+
+				"                  case D d : System.out.println(\"D\"); break;\n"+
+				"               }; \n"+
+				"       } \n"+
+				"       public static void main(String[] args) {\n"+
+				"               X.foo(new D());\n"+
+				"               Zork();\n"+
+				"       }\n"+
+				"}",
+			},
+			"----------\n" +
+			"1. ERROR in X.java (at line 6)\n" +
+			"	switch (ji) { // non-exhaustive\n" +
+			"	        ^^\n" +
+			"An enhanced switch statement should be exhaustive; a default label expected\n" +
+			"----------\n" +
+			"2. ERROR in X.java (at line 12)\n" +
+			"	Zork();\n" +
+			"	^^^^\n" +
+			"The method Zork() is undefined for the type X\n" +
+			"----------\n");
+	}
+	public void testBug578107_002() {
+		runNegativeTest(
+			new String[] {
+				"X.java",
+				"abstract sealed class C permits D {}\n"+
+				"final class D extends C {}\n"+
+				"public class X {\n"+
+				"       @SuppressWarnings(\"preview\")\n"+
+				"       static  void foo(C ji) {\n"+
+				"                switch (ji) { // non-exhaustive\n"+
+				"                  case D d : System.out.println(\"D\"); break;\n"+
+				"               }; \n"+
+				"       } \n"+
+				"       public static void main(String[] args) {\n"+
+				"               X.foo(new D());\n"+
+				"               Zork();\n"+
+				"       }\n"+
+				"}",
+			},
+			"----------\n" +
+			"1. ERROR in X.java (at line 12)\n" +
+			"	Zork();\n" +
+			"	^^^^\n" +
+			"The method Zork() is undefined for the type X\n" +
+			"----------\n");
+	}
+	public void testBug578107_003() {
+		runNegativeTest(
+			new String[] {
+				"X.java",
+				"sealed interface C permits D {}\n"+
+				"final class D implements C {}\n"+
+				"public class X {\n"+
+				"       @SuppressWarnings(\"preview\")\n"+
+				"       static  void foo(C ji) {\n"+
+				"                switch (ji) { // non-exhaustive\n"+
+				"                  case D d : System.out.println(\"D\"); break;\n"+
+				"               }; \n"+
+				"       } \n"+
+				"       public static void main(String[] args) {\n"+
+				"               X.foo(new D());\n"+
+				"               Zork();\n"+
+				"       }\n"+
+				"}",
+			},
+			"----------\n" +
+			"1. ERROR in X.java (at line 12)\n" +
+			"	Zork();\n" +
+			"	^^^^\n" +
+			"The method Zork() is undefined for the type X\n" +
+			"----------\n");
+	}
+	public void testBug578108_001() {
+		runNegativeTest(
+			new String[] {
+				"X.java",
+				"sealed abstract class C permits D {}\n"+
+				"final class D extends C {}\n"+
+				"public class X {\n"+
+				" @SuppressWarnings(\"preview\")\n"+
+				" static <T extends C> void foo(T  ji) {\n"+
+				"    switch (ji) { // exhaustive because C is sealed and abstract\n"+
+				"      case D d : System.out.println(\"D\"); break;\n"+
+				"   }; \n"+
+				" } \n"+
+				" public static void main(String[] args) {\n"+
+				"   X.foo(new D());\n"+
+				"   Zork();\n"+
+				" }\n"+
+				"}",
+			},
+			"----------\n" +
+			"1. ERROR in X.java (at line 12)\n" +
+			"	Zork();\n" +
+			"	^^^^\n" +
+			"The method Zork() is undefined for the type X\n" +
+			"----------\n");
+	}
+	public void testBug578108_002() {
+		runNegativeTest(
+			new String[] {
+				"X.java",
+				"sealed interface C permits D {}\n"+
+				"final class D implements C {}\n"+
+				"public class X {\n"+
+				" @SuppressWarnings(\"preview\")\n"+
+				" static <T extends C> void foo(T  ji) {\n"+
+				"    switch (ji) { // exhaustive because C is sealed and abstract\n"+
+				"      case D d : System.out.println(\"D\"); break;\n"+
+				"   }; \n"+
+				" } \n"+
+				" public static void main(String[] args) {\n"+
+				"   X.foo(new D());\n"+
+				"   Zork();\n"+
+				" }\n"+
+				"}",
+			},
+			"----------\n" +
+			"1. ERROR in X.java (at line 12)\n" +
+			"	Zork();\n" +
+			"	^^^^\n" +
+			"The method Zork() is undefined for the type X\n" +
+			"----------\n");
+	}
+	public void testBug578143_001() {
+		runConformTest(
+			new String[] {
+				"X.java",
+				"public class X {\n"+
+				" @SuppressWarnings(\"preview\")\n"+
+				" static  int foo(Object o) {\n"+
+				"   return switch (o) { \n"+
+				"      case X x && true -> 0;\n"+
+				"      default -> 1;\n"+
+				"   }; \n"+
+				" } \n"+
+				" public static void main(String[] args) {\n"+
+				"   System.out.println(X.foo(new X()));\n"+
+				"   System.out.println(X.foo(new Object()));\n"+
+				" }\n"+
+				"}",
+			},
+			"0\n" +
+			"1");
+	}
+	public void testBug578143_002() {
+		runConformTest(
+			new String[] {
+				"X.java",
+				"public class X {\n"+
+				" @SuppressWarnings(\"preview\")\n"+
+				" public static void main(String[] args) {\n"+
+				"     Boolean input = false;\n"+
+				"     int result = switch(input) {\n"+
+				"       case Boolean p && true -> 1;\n"+
+				"     };\n"+
+				"     System.out.println(result);\n"+
+				" }\n"+
+				"}",
+			},
+			"1");
+	}
+	public void testBug578402() {
+		runConformTest(
+				new String[] {
+					"X.java",
+					"public class X  {\n"
+					+ "enum Color{BLUE, RED, YELLOW;}\n"
+					+ "    public static void run(Color c) {\n"
+					+ "        switch(c) {\n"
+					+ "                case BLUE -> {\n"
+					+ "                    System.out.println(\"BLUE\");\n"
+					+ "                }\n"
+					+ "                case RED -> {\n"
+					+ "                    System.out.println(\"RED\");\n"
+					+ "                }\n"
+					+ "                case Object o -> {\n"
+					+ "                    System.out.println(o.toString());\n"
+					+ "                }\n"
+					+ "            }\n"
+					+ "    }"
+					+ "	public static void main(String[] args) {\n"
+					+ "		run(Color.RED);\n"
+					+ "		run(Color.BLUE);\n"
+					+ "	}\n"
+					+ "}"
+				},
+				"RED\n" +
+				"BLUE");
+	}
+	public void testBug578402_2() {
+		runConformTest(
+				new String[] {
+					"X.java",
+					"public class X  {\n"
+					+ "static final String CONST = \"abc\";\n"
+					+ "    public static void main(String args[]) {\n"
+					+ "        System.out.println(run());\n"
+					+ "    }\n"
+					+ "    public static int run() {\n"
+					+ "        String s = \"abc\";\n"
+					+ "        int a = -1;\n"
+					+ "        switch (s) {\n"
+					+ "            case CONST -> {\n"
+					+ "                a = 2;\n"
+					+ "                break;\n"
+					+ "            }\n"
+					+ "            case null -> {\n"
+					+ "                a = 0;\n"
+					+ "                break; \n"
+					+ "            }\n"
+					+ "            default -> {\n"
+					+ "            	a = 1;\n"
+					+ "            }\n"
+					+ "        }\n"
+					+ "        return a;\n"
+					+ "    }\n"
+					+ "}",
+				},
+				"2");
+	}
+	// to be enabled after bug 578417 is fixed.
+	public void _testBug578402_3() {
+		runConformTest(
+				new String[] {
+					"X.java",
+					"public class X  {\n"
+					+ "static final String CONST = \"abc\";\n"
+					+ "    public static void main(String args[]) {\n"
+					+ "        System.out.println(run());\n"
+					+ "    }\n"
+					+ "    public static int run() {\n"
+					+ "        String s = \"abc\";\n"
+					+ "        int a = -1;\n"
+					+ "        switch (s) {\n"
+					+ "            case CONST -> {\n"
+					+ "                a = 2;\n"
+					+ "                break;\n"
+					+ "            }\n"
+					+ "            case String s1 -> {\n"
+					+ "                a = 0;\n"
+					+ "                break; \n"
+					+ "            }\n"
+					+ "        }\n"
+					+ "        return a;\n"
+					+ "    }\n"
+					+ "}",
+				},
+				"2");
+	}
+	public void testBug578241_1() {
+		runConformTest(
+				new String[] {
+					"X.java",
+					"public class X {\n"
+					+ "    public static void foo(Object obj, int x) {\n"
+					+ "    	switch (obj) {\n"
+					+ "    		case String s && (switch (x) {\n"
+					+ "					case 1 -> { yield true; }\n"
+					+ "					default -> { yield false; }\n"
+					+ "   	 									})	\n"
+					+ "   	 		 			-> {\n"
+					+ "   	 		 				System.out.println(\"true\");\n"
+					+ "   	 		 			}\n"
+					+ "					\n"
+					+ "   	 		 default -> {\n"
+					+ "   	 			System.out.println(\"false\");\n"
+					+ "   	 		 }\n"
+					+ "    	}	\n"
+					+ "    }\n"
+					+ "    public static void main(String[] args) {\n"
+					+ "		foo(\"abc\", 1);\n"
+					+ "	}\n"
+					+ "}",
+				},
+				"true");
+	}
+	private String getTestCaseForBug578504 (String caseConstant) {
+		return "public class X {\n"
+				+ "    public Object literal = \"a\";\n"
+				+ "    @SuppressWarnings(\"preview\")\n"
+				+ "	public boolean foo() {\n"
+				+ "        String s = switch(literal) {\n"
+				+ "            " + caseConstant
+				+ "                yield \"a\";\n"
+				+ "            }\n"
+				+ "            case default -> { \n"
+				+ "                yield \"b\";\n"
+				+ "            }\n"
+				+ "        }; \n"
+				+ "        return s.equals(\"a\");\n"
+				+ "    }\n"
+				+ "    public static void main(String[] argv) {\n"
+				+ "    	X c = new X();\n"
+				+ "    	System.out.println(c.foo());\n"
+				+ "    }\n"
+				+ "}";
+	}
+	public void testBug578504_1() {
+		runConformTest(
+				new String[] {
+					"X.java",
+					getTestCaseForBug578504("case ((String a && a.equals(\"a\")) && a != null)  -> { \n")
+					,
+				},
+				"true");
+	}
+	public void testBug578504_2() {
+		runConformTest(
+				new String[] {
+					"X.java",
+					getTestCaseForBug578504("case ((CharSequence a && a instanceof String ss && ss == null) && ss != null)  -> {\n"),
+				},
+				"false");
+	}
+	public void testBug578504_3() {
+		runConformTest(
+				new String[] {
+					"X.java",
+					getTestCaseForBug578504("case (CharSequence a && (a instanceof String ss && ss != null) && ss != null)  -> {\n"),
+				},
+				"true");
+	}
+	public void testBug578504_4() {
+		runNegativeTest(
+				new String[] {
+					"X.java",
+					getTestCaseForBug578504("case ((CharSequence a && (a == null || a instanceof String ss)) && ss != null)  -> {\n"),
+				},
+				"----------\n" +
+				"1. ERROR in X.java (at line 6)\n" +
+				"	case ((CharSequence a && (a == null || a instanceof String ss)) && ss != null)  -> {\n" +
+				"	                                                                   ^^\n" +
+				"ss cannot be resolved to a variable\n" +
+				"----------\n");
+	}
+	public void testBug578504_5() {
+		runNegativeTest(
+				new String[] {
+					"X.java",
+					getTestCaseForBug578504("case ((CharSequence a && (a instanceof String ss || a == null)) && ss != null)  -> {\n"),
+				},
+				"----------\n" +
+				"1. ERROR in X.java (at line 6)\n" +
+				"	case ((CharSequence a && (a instanceof String ss || a == null)) && ss != null)  -> {\n" +
+				"	                                                                   ^^\n" +
+				"ss cannot be resolved to a variable\n" +
+				"----------\n");
+	}
+	public void testBug578504_6() {
+		runConformTest(
+				new String[] {
+					"X.java",
+					getTestCaseForBug578504("case ((CharSequence a && (a instanceof String ss && a instanceof String sss)) && ss == sss)  -> {\n"),
+				},
+				"true");
+	}
+	public void testBug578504_7() {
+		runConformTest(
+				new String[] {
+					"X.java",
+					getTestCaseForBug578504("case ((CharSequence a && (a instanceof String ss && a instanceof String sss)) && ss != sss)  -> {\n"),
+				},
+				"false");
+	}
+	public void testBug578553_1() {
+		runConformTest(
+				new String[] {
+					"X.java",
+					"public class X {\n"
+					+ "	@SuppressWarnings(\"preview\")\n"
+					+ "	static Long foo(Number n) {\n"
+					+ "		return switch (n) {\n"
+					+ "	     case (Long l) && l.toString().equals(\"0\") -> {\n"
+					+ "	    	 yield ++l;\n"
+					+ "	     }\n"
+					+ "		default -> throw new IllegalArgumentException();\n"
+					+ "	   };\n"
+					+ "	}\n"
+					+ "	public static void main(String[] args) {\n"
+					+ "		System.out.println(foo(0L));\n"
+					+ "	}\n"
+					+ "}",
+				},
+				"1");
+	}
+	public void testBug578553_2() {
+		runConformTest(
+				new String[] {
+					"X.java",
+					"public class X {\n"
+					+ "		@SuppressWarnings(\"preview\")\n"
+					+ "	static Long foo(Number n) {  \n"
+					+ "		return switch (n) { \n"
+					+ "	     case (Long l) && l.toString().equals(\"0\") -> {\n"
+					+ "	    	 yield switch(l) {\n"
+					+ "	    	 case Long l1 && l1.toString().equals(l1.toString()) -> {\n"
+					+ "	    	 	yield ++l + ++l1;\n"
+					+ "	    	 }\n"
+					+ "			default -> throw new IllegalArgumentException(\"Unexpected value: \" + l);\n"
+					+ "	    	 };\n"
+					+ "	     }\n"
+					+ "		default -> throw new IllegalArgumentException();\n"
+					+ "	   };\n"
+					+ "	}\n"
+					+ "	public static void main(String[] args) {\n"
+					+ "		System.out.println(foo(0L));\n"
+					+ "	}\n"
+					+ "}",
+				},
+				"2");
+	}
+	public void testBug578553_3() {
+		runNegativeTest(
+				new String[] {
+					"X.java",
+					"public class X {\n"
+					+ "	@SuppressWarnings(\"preview\")\n"
+					+ "	static Long foo(Number n) {  \n"
+					+ "		return switch (n) { \n"
+					+ "	     case (Long l) && l.toString().equals(\"0\") -> {\n"
+					+ "	    	 yield switch(l) {\n"
+					+ "	    	 case Long l1 && l.toString().equals(l1.toString()) -> {\n"
+					+ "	    	 	yield ++l + ++l1;\n"
+					+ "	    	 }\n"
+					+ "			default -> throw new IllegalArgumentException(\"Unexpected value: \" + l);\n"
+					+ "	    	 };\n"
+					+ "	     }\n"
+					+ "		default -> throw new IllegalArgumentException();\n"
+					+ "	   };\n"
+					+ "	}\n"
+					+ "}",
+				},
+				"----------\n" +
+				"1. ERROR in X.java (at line 7)\n" +
+				"	case Long l1 && l.toString().equals(l1.toString()) -> {\n" +
+				"	                ^\n" +
+				"Local variable l referenced from a guard must be final or effectively final\n" +
+				"----------\n");
+	}
+	public void testBug578553_4() {
+		runNegativeTest(
+				new String[] {
+					"X.java",
+					"public class X {\n"
+					+ "	@SuppressWarnings(\"preview\")\n"
+					+ "	static Long foo(Number n) {  \n"
+					+ "	int i = 0;\n"
+					+ "	return switch(n) {\n"
+					+ "	  case Long l && (1 == switch(l) {\n"
+					+ "		case \n"
+					+ "			default -> {  \n"
+					+ "				yield (i++);\n"
+					+ "			} \n"
+					+ "		}) -> 1L; \n"
+					+ "	  default -> throw new IllegalArgumentException(\"Unexpected value: \" + n);\n"
+					+ "	  };\n"
+					+ "	}\n"
+					+ "}",
+				},
+				"----------\n" +
+				"1. ERROR in X.java (at line 9)\n" +
+				"	yield (i++);\n" +
+				"	       ^\n" +
+				"Local variable i referenced from a guard must be final or effectively final\n" +
+				"----------\n");
+	}
+	public void testBug578553_5() {
+		runNegativeTest(
+				new String[] {
+					"X.java",
+					"public class X {\n"
+					+ "	@SuppressWarnings(\"preview\")\n"
+					+ "	static Long foo(Number n) {  \n"
+					+ "	int i = 0;\n"
+					+ "	return switch(n) {\n"
+					+ "	  case Long l && (1 == switch(l) {\n"
+					+ "		case \n"
+					+ "			default -> {  \n"
+					+ "				yield ++i;\n"
+					+ "			} \n"
+					+ "		}) -> 1L; \n"
+					+ "	  default -> throw new IllegalArgumentException(\"Unexpected value: \" + n);\n"
+					+ "	  };\n"
+					+ "	}\n"
+					+ "}",
+				},
+				"----------\n" +
+				"1. ERROR in X.java (at line 9)\n" +
+				"	yield ++i;\n" +
+				"	        ^\n" +
+				"Local variable i referenced from a guard must be final or effectively final\n" +
+				"----------\n");
+	}
+	public void testBug578553_6() {
+		runNegativeTest(
+				new String[] {
+					"X.java",
+					"public class X {\n"
+					+ "	@SuppressWarnings(\"preview\")\n"
+					+ "	static Long foo(Number n) {  \n"
+					+ "	int i = 0;\n"
+					+ "	return switch(n) {\n"
+					+ "	  case Long l && (1 == switch(l) {\n"
+					+ "		case \n"
+					+ "			default -> {  \n"
+					+ "				yield (i=i+1);\n"
+					+ "			} \n"
+					+ "		}) -> 1L; \n"
+					+ "	  default -> throw new IllegalArgumentException(\"Unexpected value: \" + n);\n"
+					+ "	  };\n"
+					+ "	}\n"
+					+ "}",
+				},
+				"----------\n" +
+				"1. ERROR in X.java (at line 9)\n" +
+				"	yield (i=i+1);\n" +
+				"	       ^\n" +
+				"Local variable i referenced from a guard must be final or effectively final\n" +
+				"----------\n");
+	}
+	public void testBug578553_7() {
+		runNegativeTest(
+				new String[] {
+					"X.java",
+					"public class X {\n"
+					+ " static int bar() { return 1; }\n"
+					+ "	@SuppressWarnings(\"preview\")\n"
+					+ "	static Long foo(Number n) {  \n"
+					+ "	int i = 0;\n"
+					+ "	return switch(n) {\n"
+					+ "	  case Long l && (1 == switch(l) {\n"
+					+ "		case \n"
+					+ "			default -> {  \n"
+					+ "				yield (i = bar());\n"
+					+ "			} \n"
+					+ "		}) -> 1L; \n"
+					+ "	  default -> throw new IllegalArgumentException(\"Unexpected value: \" + n);\n"
+					+ "	  };\n"
+					+ "	}\n"
+					+ "}",
+				},
+				"----------\n" +
+				"1. ERROR in X.java (at line 10)\n" +
+				"	yield (i = bar());\n" +
+				"	       ^\n" +
+				"Local variable i referenced from a guard must be final or effectively final\n" +
+				"----------\n");
+	}
+	public void testBug578568_1() {
+		runConformTest(
+				new String[] {
+						"X.java",
+						"public class X {\n"
+								+ "    @SuppressWarnings(\"preview\")\n"
+								+ "	public static int foo(Number arg0) {\n"
+								+ "        int result = 0;\n"
+								+ "        result = \n"
+								+ "         switch (arg0) {\n"
+								+ "            case Object p -> {\n"
+								+ "                switch (arg0) {\n"
+								+ "                     case Number p1 -> {\n"
+								+ "                        yield 1;\n"
+								+ "                    }\n"
+								+ "                }\n"
+								+ "            }\n"
+								+ "        }; \n"
+								+ "        return result;\n"
+								+ "    }\n"
+								+ " public static void main(String[] args) {\n"
+								+ "    	System.out.println(foo(0L));\n"
+								+ "	}"
+								+ "}",
+				},
+				"1");
+	}
+	public void testBug578568_2() {
+		runConformTest(
+				new String[] {
+						"X.java",
+						"public class X {\n"
+								+ " @SuppressWarnings(\"preview\")\n"
+								+ "	public static int foo(Number arg0) {\n"
+								+ "        return switch (arg0) {\n"
+								+ "            case Object p : {\n"
+								+ "                switch (arg0) {\n"
+								+ "                     case Number p1 : {\n"
+								+ "                        yield 1;\n"
+								+ "                    }\n"
+								+ "                }\n"
+								+ "            }\n"
+								+ "        }; \n"
+								+ "    }\n"
+								+ " public static void main(String[] args) {\n"
+								+ "    	System.out.println(foo(0L));\n"
+								+ "	}"
+								+ "}",
+				},
+				"1");
+	}
+	public void testBug578568_3() {
+		runNegativeTest(
+				new String[] {
+						"X.java",
+						"public class X {\n"
+								+ " @SuppressWarnings(\"preview\")\n"
+								+ "	public static int foo(Object arg0) {\n"
+								+ "        return switch (arg0) {\n"
+								+ "            case Object p : {\n"
+								+ "                switch (arg0) {\n"
+								+ "                    case Number p1 : {\n"
+								+ "                        yield 1;\n"
+								+ "                    }\n"
+								+ "                    default: {\n"
+								+ "                    }"
+								+ "                }\n"
+								+ "            }\n"
+								+ "        }; \n"
+								+ " }\n"
+								+ "}",
+				},
+				"----------\n" +
+				"1. ERROR in X.java (at line 12)\n" +
+				"	}\n" +
+				"	^^\n" +
+				"A switch labeled block in a switch expression should not complete normally\n" +
+				"----------\n");
+	}
+	public void testBug578416() {
+		runConformTest(new String[] {
+				"X.java",
+				"public class X {\n"
+				+ "    public static int testMethod(I i) {\n"
+				+ "       return switch (i) {\n"
+				+ "            case I p1 && (p1 instanceof C p2) : {\n"
+				+ "                yield p2.value(); // Error here\n"
+				+ "            }\n"
+				+ "            case I p3 : {\n"
+				+ "                yield p3.value(); // No error here\n"
+				+ "            }\n"
+				+ "        };\n"
+				+ "    }\n"
+				+ "    interface I {\n"
+				+ "        public int value();\n"
+				+ "    }\n"
+				+ "    class C implements I {\n"
+				+ "    	@Override\n"
+				+ "    	public int value() {\n"
+				+ "    		return 0;\n"
+				+ "    	}\n"
+				+ "    }\n"
+				+ "    public static void main(String[] args) {\n"
+				+ "    	I i = new I() {\n"
+				+ "    		public int value() {\n"
+				+ "    			return 10;\n"
+				+ "    		} \n"
+				+ "    	}; \n"
+				+ "    	System.out.println(testMethod(i));\n"
+				+ "    	System.out.println(testMethod(new X().new C()));\n"
+				+ "	}"
+				+ "}\n"},
+				"10\n" +
+				"0");
+	}
+	public void testBug578416_1() {
+		runConformTest(new String[] {
+				"X.java",
+				"public class X {\n"
+				+ "    public static int testMethod(I i) {\n"
+				+ "       return switch (i) {\n"
+				+ "            case I p1 && (p1 instanceof C p2) : {\n"
+				+ "                yield p2.value();\n"
+				+ "            }\n"
+				+ "            case I p3 : {\n"
+				+ "                yield p3.value();\n"
+				+ "            }\n"
+				+ "        };\n"
+				+ "    }\n"
+				+ "    interface I {\n"
+				+ "        public int value();\n"
+				+ "    }\n"
+				+ "    class C implements I {\n"
+				+ "    	@Override\n"
+				+ "    	public int value() {\n"
+				+ "    		return 0;\n"
+				+ "    	}\n"
+				+ "    }\n"
+				+ "    public static void main(String[] args) {\n"
+				+ "    	I i = new I() {\n"
+				+ "    		public int value() {\n"
+				+ "    			return 10;\n"
+				+ "    		} \n"
+				+ "    	}; \n"
+				+ "    	System.out.println(testMethod(i));\n"
+				+ "    	System.out.println(testMethod(new X().new C()));\n"
+				+ "	}"
+				+ "}\n"},
+				"10\n" +
+				"0");
+	}
+	public void testBug578416_2() {
+		runConformTest(new String[] {
+				"X.java",
+				"public class X {\n"
+				+ "    public static int foo(Object o) {\n"
+				+ "       return switch (o) {\n"
+				+ "            case Number n && (n instanceof Integer i) : {\n"
+				+ "                yield n.intValue() + i; // Error here\n"
+				+ "            }\n"
+				+ "            case Number n2 : {\n"
+				+ "                yield n2.intValue();\n"
+				+ "            }\n"
+				+ "            default : {\n"
+				+ "                yield -1;\n"
+				+ "            }\n"
+				+ "        };\n"
+				+ "    }\n"
+				+ "    public static void main(String[] args) {\n"
+				+ "    	System.out.println(foo(new Integer(10)));\n"
+				+ "    	System.out.println(foo(new Integer(5)));\n"
+				+ "    	System.out.println(foo(new Long(5L)));\n"
+				+ "    	System.out.println(foo(new Float(0)));\n"
+				+ "	}"
+				+ "}\n"},
+				"20\n" +
+				"10\n" +
+				"5\n" +
+				"0");
+	}
+	public void testBug578416_3() {
+		runConformTest(new String[] {
+				"X.java",
+				"public class X {\n"
+				+ "    public static int foo(Object o) {\n"
+				+ "       return switch (o) {\n"
+				+ "            case Number n && (n instanceof Integer i && i.equals(10)) : {\n"
+				+ "                yield n.intValue() + i; // Error here\n"
+				+ "            }\n"
+				+ "            case Number n2 : {\n"
+				+ "                yield n2.intValue();\n"
+				+ "            }\n"
+				+ "            default : {\n"
+				+ "                yield -1;\n"
+				+ "            }\n"
+				+ "        };\n"
+				+ "    }\n"
+				+ "    public static void main(String[] args) {\n"
+				+ "    	System.out.println(foo(new Integer(10)));\n"
+				+ "    	System.out.println(foo(new Integer(5)));\n"
+				+ "    	System.out.println(foo(new Long(5L)));\n"
+				+ "    	System.out.println(foo(new Float(0)));\n"
+				+ "	}"
+				+ "}\n"},
+				"20\n" +
+				"5\n" +
+				"5\n" +
+				"0");
+	}
+	public void testBug578635_1() {
+		runConformTest(new String[] {
+				"X.java",
+				"public class X {\n"
+				+ "   @SuppressWarnings({ \"preview\", \"rawtypes\" })\n"
+				+ "	public static boolean foo(Integer n) {\n"
+				+ "    	return switch (n) {\n"
+				+ "	    	case Integer x && x.equals(10) -> {\n"
+				+ "	    		yield true;\n"
+				+ "	    	}\n"
+				+ "	    	case Comparable y -> {\n"
+				+ "	    		yield false;\n"
+				+ "	    	}\n"
+				+ "    	};\n"
+				+ "    }\n"
+				+ "    public static void main(String[] argv) {\n"
+				+ "    	System.out.println(foo(Integer.valueOf(0)));\n"
+				+ "    	System.out.println(foo(Integer.valueOf(10)));\n"
+				+ "    }\n"
+				+ "}"},
+				"false\n" +
+				"true");
+	}
+	public void testBug578635_2() {
+		runNegativeTest(new String[] {
+				"X.java",
+				"public class X {\n"
+				+ " @SuppressWarnings({ \"preview\", \"rawtypes\" })\n"
+				+ "	public static boolean foo(Integer n) {\n"
+				+ "    	return switch (n) {\n"
+				+ "	    	case Integer x && x.equals(10) -> {\n"
+				+ "	    		yield true;\n"
+				+ "	    	}\n"
+				+ "	    	case Comparable y -> {\n"
+				+ "	    		yield false;\n"
+				+ "	    	}\n"
+				+ "	    	default -> {\n"
+				+ "	    		yield false;\n"
+				+ "	    	}\n"
+				+ "    	};\n"
+				+ "    }\n"
+				+ "    public static void main(String[] argv) {\n"
+				+ "    	System.out.println(foo(Integer.valueOf(0)));\n"
+				+ "    	System.out.println(foo(Integer.valueOf(10)));\n"
+				+ "    }\n"
+				+ "}"},
+				"----------\n" +
+				"1. ERROR in X.java (at line 11)\n" +
+				"	default -> {\n" +
+				"	^^^^^^^\n" +
+				"Switch case cannot have both a total pattern and default label\n" +
+				"----------\n");
+	}
+	public void testBug578635_3() {
+		runNegativeTest(new String[] {
+				"X.java",
+				"public class X {\n"
+				+ " @SuppressWarnings({ \"preview\", \"rawtypes\" })\n"
+				+ "	public static boolean foo(Integer n) {\n"
+				+ "    	return switch (n) {\n"
+				+ "	    	case Integer x && x.equals(10) -> {\n"
+				+ "	    		yield true;\n"
+				+ "	    	}\n"
+				+ "	    	case Comparable y -> {\n"
+				+ "	    		yield false;\n"
+				+ "	    	}\n"
+				+ "	    	default -> {\n"
+				+ "	    		yield false;\n"
+				+ "	    	}\n"
+				+ "    	};\n"
+				+ "    }\n"
+				+ "    public static void main(String[] argv) {\n"
+				+ "    	System.out.println(foo(Integer.valueOf(0)));\n"
+				+ "    	System.out.println(foo(Integer.valueOf(10)));\n"
+				+ "    }\n"
+				+ "}"},
+				"----------\n" +
+				"1. ERROR in X.java (at line 11)\n" +
+				"	default -> {\n" +
+				"	^^^^^^^\n" +
+				"Switch case cannot have both a total pattern and default label\n" +
+				"----------\n");
+	}
+	public void testBug578417_1() {
+		runConformTest(new String[] {
+				"X.java",
+				"public class X {\n"
+				+ "   @SuppressWarnings({ \"preview\", \"rawtypes\" })\n"
+				+ "    static final String CONSTANT = \"abc\";\n"
+				+ "    static String CON2 = \"abc\";\n"
+				+ "    public static int foo() {\n"
+				+ "        int res = 0;\n"
+				+ "        switch (CON2) {\n"
+				+ "            case CONSTANT -> {\n"
+				+ "                res = 1;\n"
+				+ "                break;\n"
+				+ "            }\n"
+				+ "            case String s -> {\n"
+				+ "                res = 2;\n"
+				+ "                break;\n"
+				+ "            }\n"
+				+ "        }\n"
+				+ "        return res;\n"
+				+ "    }\n"
+				+ "    public static void main(String argv[]) {\n"
+				+ "    	System.out.println(foo()); \n"
+				+ "    }\n"
+				+ "}"},
+				"1" );
+	}
+	public void testBug578132_001() {
+		runConformTest(
+				new String[] {
+					"X.java",
+					"public class X {\n"+
+					" @SuppressWarnings(\"preview\")\n"+
+					" static  int foo(Object o, boolean b) {\n"+
+					"   return switch (o) { \n"+
+					"      case X x && b -> 0; // compilation error\n"+
+					"      default -> 1;\n"+
+					"   }; \n"+
+					" } \n"+
+					" public static void main(String[] args) {\n"+
+					"   System.out.println(X.foo(new X(), true));\n"+
+					"   System.out.println(X.foo(new Object(), true));\n"+
+					" }\n"+
+					"}"
+				},
+				"0\n"+
+				"1");
+	}
+	public void test576788_1() {
+		runConformTest(
+				new String[] {
+					"X.java",
+					"public class X {\n"+
+					" @SuppressWarnings(\"preview\")\n"+
+					"     public static void foo1(Object o) {\n"
+					+ "    	boolean b = switch (o) {\n"
+					+ "    		case String s, null -> {\n"
+					+ "    			yield s == null;\n"
+					+ "    		}\n"
+					+ "    		default -> true;\n"
+					+ "    	};\n"
+					+ "    	System.out.println(b);\n"
+					+ "    } \n"
+					+ "    public static void main(String[] argv) {\n"
+					+ "    	foo1(null);\n"
+					+ "    	foo1(\"abc\");\n"
+					+ "    }\n"+
+					"}"
+				},
+				"true\n"+
+				"false");
+	}
+	public void testBug577374_001() {
+		runConformTest(
+				new String[] {
+					"X.java",
+					"public class X {\n"+
+					"    sealed interface A {}\n"+
+					"    sealed interface B1 extends A {}\n"+
+					"    sealed interface B2 extends A {}\n"+
+					"    sealed interface C extends A {}\n"+
+					"    final class D1 implements B1, C {}\n"+
+					"    final class D2 implements B2, C {}\n"+
+					"    \n"+
+					"    public static int test(A arg) {\n"+
+					"        return switch (arg) {\n"+
+					"            case B1 b1 -> 1;\n"+
+					"            case B2 b2 -> 2;\n"+
+					"        };\n"+
+					"    }\n"+
+					"    public static void main(String[] args) {\n"+
+					"   X.D1 d1 = new X().new D1();\n"+
+					"   System.out.println(X.test(d1));\n"+
+					" }\n"+
+					"}"
+				},
+				"1");
+	}
+	public void testBug579355_001() {
+		runConformTest(
+				new String[] {
+					"X.java",
+					"public class X {\n"+
+					"       static void constantLabelMustAppearBeforePattern(Integer o) {\n"+
+					"               switch (o) {\n"+
+					"               case -1, 1 -> System.out.println(\"special case:\" + o);\n"+
+					"               case Integer i && i > 0 -> System.out.println(\"positive integer: \" + o);\n"+
+					"               case Integer i -> System.out.println(\"other integer: \" + o);\n"+
+					"               }\n"+
+					"       }\n"+
+					"\n"+
+					"       public static void main(String[] args) {\n"+
+					"               X.constantLabelMustAppearBeforePattern(-10);\n"+
+					"               X.constantLabelMustAppearBeforePattern(-1);\n"+
+					"               X.constantLabelMustAppearBeforePattern(0);\n"+
+					"               X.constantLabelMustAppearBeforePattern(1);\n"+
+					"               X.constantLabelMustAppearBeforePattern(10);\n"+
+					"       } \n"+
+					"}"
+				},
+				"other integer: -10\n" +
+				"special case:-1\n" +
+				"other integer: 0\n" +
+				"special case:1\n" +
+				"positive integer: 10");
+	}
+	public void testBug579355_002() {
+		runConformTest(
+				new String[] {
+					"X.java",
+					"public class X {\n"+
+					"       static void constantLabelMustAppearBeforePattern(Integer o) {\n"+
+					"               switch (o) {\n"+
+					"               case -1, 1 -> System.out.println(\"special case:\" + o);\n"+
+					"               case null -> System.out.println(\"null\");\n"+
+					"               case Integer i && i > 0 -> System.out.println(\"positive integer: \" + o);\n"+
+					"               case Integer i -> System.out.println(\"other integer: \" + o);\n"+
+					"               }\n"+
+					"       }\n"+
+					"\n"+
+					"       public static void main(String[] args) {\n"+
+					"               X.constantLabelMustAppearBeforePattern(-10);\n"+
+					"               X.constantLabelMustAppearBeforePattern(-1);\n"+
+					"               X.constantLabelMustAppearBeforePattern(0);\n"+
+					"               X.constantLabelMustAppearBeforePattern(1);\n"+
+					"               X.constantLabelMustAppearBeforePattern(10);\n"+
+					"               X.constantLabelMustAppearBeforePattern(null);\n"+
+					"       } \n"+
+					"}"
+				},
+				"other integer: -10\n" +
+				"special case:-1\n" +
+				"other integer: 0\n" +
+				"special case:1\n" +
+				"positive integer: 10\n"+
+				"null");
+	}
+	public void testBug579355_003() {
+		runNegativeTest(
+				new String[] {
+					"X.java",
+					"public class X {\n"+
+					"           public int foo(Integer i) {\n"
+					+ "        int result = 0;\n"
+					+ "        switch (i) {\n"
+					+ "            case 0 -> {\n"
+					+ "                result = 3;\n"
+					+ "                break;\n"
+					+ "            }\n"
+					+ "            case null -> {\n"
+					+ "                result = 5;\n"
+					+ "                break;\n"
+					+ "            }\n"
+					+ "            case (Integer p) -> {\n"
+					+ "                result = 6;\n"
+					+ "                break;\n"
+					+ "            }\n"
+					+ "            case 10 -> {\n"
+					+ "                result = 9;\n"
+					+ "                break;\n"
+					+ "            }\n"
+					+ "        }   \n"
+					+ "        return result;\n"
+					+ "    }\n"+
+					"}"
+				},
+				"----------\n" +
+				"1. ERROR in X.java (at line 17)\n" +
+				"	case 10 -> {\n" +
+				"	     ^^\n" +
+				"This case label is dominated by one of the preceding case label\n" +
+				"----------\n");
+	}
+	public void testBug579355_004() {
+		runConformTest(
+				new String[] {
+					"X.java",
+					"public class X {\n"+
+					"    public static Color color = Color.BLUE;\n"
+					+ "    public static void main(String args[]) {\n"
+					+ "        Color c; \n"
+					+ "        var result = switch(color){\n"
+					+ "                case BLUE ->  (c = color) == Color.BLUE;\n"
+					+ "                case RED, GREEN ->  (c = color) + \"text\";\n"
+					+ "                case YELLOW ->  new String((c = color) + \"text\");\n"
+					+ "                default ->  (c = color);\n"
+					+ "                };\n"
+					+ "        if (result != null && c == Color.BLUE) {\n"
+					+ "        	System.out.println(\"Pass\");\n"
+					+ "        } else {\n"
+					+ "        	System.out.println(\"Fail\");\n"
+					+ "        }\n"
+					+ "    } \n"
+					+ "}\n"
+					+ "enum Color{BLUE, RED, GREEN, YELLOW;}"
+				},
+				"Pass");
+	}
+	public void testBug579355_005() {
+		runConformTest(
+				new String[] {
+					"X.java",
+					"public class X {\n"+
+					"    public int foo(Character c) {\n"
+					+ "        int result = 0;\n"
+					+ "        result = switch (c) {\n"
+					+ "            case Character c1 -> 1;\n"
+					+ "            case (short)1 -> 5;\n"
+					+ "        };\n"
+					+ "        return result;\n"
+					+ "    }\n"
+					+ "    public static void main(String args[]) {\n"
+					+ "    	X x = new X();\n"
+					+ "    	if (x.foo('\\u0001') == 1) {\n"
+					+ "            System.out.println(\"Pass\");\n"
+					+ "        } else {\n"
+					+ "        	System.out.println(\"Fail\");\n"
+					+ "        }\n"
+					+ "    }\n"
+					+ "}"
+				},
+				"Pass");
+	}
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java
index 06ade41..ff99a82 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2021 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -175,6 +175,7 @@
 	since_9.add(NullAnnotationTests9.class);
 	since_9.add(AnnotationTest_9.class);
 	since_9.add(JavadocTestForModule.class);
+	since_9.add(TryStatement9Test.class);
 
 	// add 10 specific test here (check duplicates)
 	ArrayList since_10 = new ArrayList();
@@ -222,9 +223,13 @@
 	 // add 17 specific test here (check duplicates)
 	 ArrayList since_17 = new ArrayList();
 	 since_17.add(SealedTypesTests.class);
-	 since_17.add(SwitchPatternTest.class);
 	 since_17.add(InstanceofPrimaryPatternTest.class);
-	 since_17.add(NullAnnotationTests17.class);
+
+	 // add 18 specific test here (check duplicates)
+	 ArrayList since_18 = new ArrayList();
+	 since_18.add(SwitchPatternTest.class);
+	 since_18.add(NullAnnotationTests18.class);
+	 since_18.add(JavadocTest_18.class);
 
 	 // Build final test suite
 	TestSuite all = new TestSuite(TestAll.class.getName());
@@ -423,6 +428,26 @@
 		TestCase.resetForgottenFilters(tests_17);
 		all.addTest(AbstractCompilerTest.buildComplianceTestSuite(ClassFileConstants.getComplianceLevelForJavaVersion(ClassFileConstants.MAJOR_VERSION_17), tests_17));
 	}
+	if ((possibleComplianceLevels & AbstractCompilerTest.F_18) != 0) {
+		ArrayList tests_18 = (ArrayList)standardTests.clone();
+		tests_18.addAll(since_1_4);
+		tests_18.addAll(since_1_5);
+		tests_18.addAll(since_1_6);
+		tests_18.addAll(since_1_7);
+		tests_18.addAll(since_1_8);
+		tests_18.addAll(since_9);
+		tests_18.addAll(since_10);
+		tests_18.addAll(since_11);
+		tests_18.addAll(since_12);
+		tests_18.addAll(since_13);
+		tests_18.addAll(since_14);
+		tests_18.addAll(since_15);
+		tests_18.addAll(since_16);
+		tests_18.addAll(since_17);
+		tests_18.addAll(since_18);
+		TestCase.resetForgottenFilters(tests_18);
+		all.addTest(AbstractCompilerTest.buildComplianceTestSuite(ClassFileConstants.getComplianceLevelForJavaVersion(ClassFileConstants.MAJOR_VERSION_18), tests_18));
+	}
 	all.addTest(new TestSuite(Jsr14Test.class));
 	return all;
 }
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 0c60d32..9d0fd9e 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
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2020, 2021 IBM Corporation and others.
+ * Copyright (c) 2020, 2022 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
@@ -1582,4 +1582,40 @@
 				getCompilerOptions(),
 				new String[] {"--enable-preview"});
 	}
+	public void testBug578649_1() {
+		runConformTest(
+				new String[] {
+						"X.java",
+						"public class X {\n" +
+						"    public static void main(String[] args) {\n"
+						+ "        System.out.println(\"\"\"\n"
+						+ "        <record>\n"
+						+ "          <value field=\\\"NAME2\\\">b\\tc</value>\n"
+						+ "          <value field=\\\"NAME1\\\">a\\tb</value>\n"
+						+ "        </record>\n"
+						+ "        \"\"\");\n"
+						+ "    }\n" +
+						"}\n"
+				},
+				"<record>\n" +
+				"  <value field=\"NAME2\">b	c</value>\n" +
+				"  <value field=\"NAME1\">a	b</value>\n" +
+				"</record>",
+				getCompilerOptions());
+	}
+	public void testBug578649_2() {
+		runConformTest(
+				new String[] {
+						"X.java",
+						"public class X {\n" +
+						"    public static void main(String[] args) {\n"
+						+ "        System.out.println(\"\"\"\n"
+						+ "        123\\b45\n"
+						+ "        \"\"\");\n"
+						+ "    }\n" +
+						"}\n"
+				},
+				"123\b45",
+				getCompilerOptions());
+	}
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryStatement9Test.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryStatement9Test.java
index 70d0ba5..39465fc 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryStatement9Test.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryStatement9Test.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2016 IBM corporation and others.
+ * Copyright (c) 2016, 2022 IBM corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -230,7 +230,12 @@
 			"}",
 		},
 		"----------\n" +
-		"1. ERROR in X.java (at line 15)\n" +
+		"1. WARNING in X.java (at line 14)\n" +
+		"	y1 = new Y();\n" +
+		"	^^^^^^^^^^^^\n" +
+		"Resource leak: \'y1\' is not closed at this location\n" +
+		"----------\n" +
+		"2. ERROR in X.java (at line 15)\n" +
 		"	try (y1) { \n" +
 		"	     ^^\n" +
 		"Local variable y1 defined in an enclosing scope must be final or effectively final\n" +
@@ -710,7 +715,31 @@
 		"Unhandled exception type IOException thrown by automatic close() invocation on z\n" +
 		"----------\n");
 }
-
+public void testBug577128_1() {
+	this.runConformTest(
+		new String[] {
+			"X.java",
+			"import java.io.IOException;\n" +
+			"public class X implements AutoCloseable {\n" +
+			"	private void release() {\n"
+			+ "		X cl = new X();\n"
+			+ "		try (this;cl) {} \n"
+			+ "        	catch (IOException e) {\n"
+			+ "        }\n"
+			+ "	}\n"
+			+ "	public static void main(String[] args) {\n"
+			+ "		X cl = new X();\n"
+			+ "		cl.release();\n"
+			+ "	}\n"
+			+ "	@Override\n"
+			+ "	public void close() throws IOException {\n"
+			+ "		System.out.println(\"close() call\");\n"
+			+ "	}\n"
+			+ "}\n",
+		},
+		"close() call\n" +
+		"close() call");
+}
 
 public static Class testClass() {
 	return TryStatement9Test.class;
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/AbstractCompilerTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/AbstractCompilerTest.java
index 74a0c47..962e6fd 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/AbstractCompilerTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/AbstractCompilerTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2021 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -49,6 +49,7 @@
 	public static final int F_15  = 0x1000;
 	public static final int F_16  = 0x2000;
 	public static final int F_17  = 0x4000;
+	public static final int F_18  = 0x8000;
 
 	public static final boolean RUN_JAVAC = CompilerOptions.ENABLED.equals(System.getProperty("run.javac"));
 	public static final boolean PERFORMANCE_ASSERTS = !CompilerOptions.DISABLED.equals(System.getProperty("jdt.performance.asserts"));
@@ -68,6 +69,7 @@
 	protected static boolean isJRE15Plus = false;
 	protected static boolean isJRE16Plus = false;
 	protected static boolean isJRE17Plus = false;
+	protected static boolean isJRE18Plus = false;
 	protected static boolean reflectNestedClassUseDollar;
 
 	public static int[][] complianceTestLevelMapping = new int[][] {
@@ -86,6 +88,7 @@
 		new int[] {F_15, ClassFileConstants.MAJOR_VERSION_15},
 		new int[] {F_16, ClassFileConstants.MAJOR_VERSION_16},
 		new int[] {F_17, ClassFileConstants.MAJOR_VERSION_17},
+		new int[] {F_18, ClassFileConstants.MAJOR_VERSION_18},
 	};
 
 	/**
@@ -315,7 +318,8 @@
 	public static int getPossibleComplianceLevels() {
 		if (possibleComplianceLevels == UNINITIALIZED) {
 			String specVersion = System.getProperty("java.specification.version");
-			isJRE17Plus =  CompilerOptions.VERSION_17.equals(specVersion);
+			isJRE18Plus =  CompilerOptions.VERSION_18.equals(specVersion);
+			isJRE17Plus =  isJRE18Plus || CompilerOptions.VERSION_17.equals(specVersion);
 			isJRE16Plus = isJRE17Plus || CompilerOptions.VERSION_16.equals(specVersion);
 			isJRE15Plus = isJRE16Plus || CompilerOptions.VERSION_15.equals(specVersion);
 			isJRE14Plus = isJRE15Plus || CompilerOptions.VERSION_14.equals(specVersion);
@@ -372,6 +376,9 @@
 					} else if (CompilerOptions.VERSION_17.equals(compliance)) {
 						if (isJRE17Plus)
 							possibleComplianceLevels |= F_17;
+					} else if (CompilerOptions.VERSION_18.equals(compliance)) {
+						if (isJRE18Plus)
+							possibleComplianceLevels |= F_18;
 					} else {
 						System.out.println("Ignoring invalid compliance (" + compliance + ")");
 						System.out.print("Use one of ");
@@ -389,7 +396,9 @@
 						System.out.print(CompilerOptions.VERSION_13 + ", ");
 						System.out.println(CompilerOptions.VERSION_14 + ", ");
 						System.out.println(CompilerOptions.VERSION_15 + ", ");
-						System.out.println(CompilerOptions.VERSION_16);
+						System.out.println(CompilerOptions.VERSION_16 + ", ");
+						System.out.println(CompilerOptions.VERSION_17 + ", ");
+						System.out.println(CompilerOptions.VERSION_18);
 					}
 				}
 				if (possibleComplianceLevels == 0) {
@@ -459,6 +468,10 @@
 					if (canRun17) {
 						possibleComplianceLevels |= F_17;
 					}
+					boolean canRun18 = canRun17 && !CompilerOptions.VERSION_17.equals(specVersion);
+					if (canRun18) {
+						possibleComplianceLevels |= F_18;
+					}
 				} else if ("1.0".equals(specVersion)
 							|| CompilerOptions.VERSION_1_1.equals(specVersion)
 							|| CompilerOptions.VERSION_1_2.equals(specVersion)
@@ -491,6 +504,9 @@
 																possibleComplianceLevels |= F_16;
 																if (!CompilerOptions.VERSION_16.equals(specVersion)) {
 																	possibleComplianceLevels |= F_17;
+																	if (!CompilerOptions.VERSION_17.equals(specVersion)) {
+																		possibleComplianceLevels |= F_18;
+																	}
 																}
 															}
 														}
@@ -671,7 +687,7 @@
 	}
 
 	protected static String getVersionString(long compliance) {
-		String version = "version 16 : 60.0";
+		String version = "version 17 : 61.0";
 		if (compliance < ClassFileConstants.JDK9) return "version 1.8 : 52.0";
 		if (compliance == ClassFileConstants.JDK9) return "version 9 : 53.0";
 		if (compliance == ClassFileConstants.JDK10) return "version 10 : 54.0";
@@ -680,7 +696,7 @@
 			int major = Integer.parseInt(ver) + ClassFileConstants.MAJOR_VERSION_0;
 			return "version " + ver + " : " + major + ".0";
 		}
-		if (compliance >= ClassFileConstants.getComplianceLevelForJavaVersion(ClassFileConstants.MAJOR_VERSION_17)) return version; // keep this stmt for search for next bump up
+		if (compliance >= ClassFileConstants.getComplianceLevelForJavaVersion(ClassFileConstants.MAJOR_VERSION_18)) return version; // keep this stmt for search for next bump up
 		return version;
 	}
 
diff --git a/org.eclipse.jdt.core.tests.model/JCL/jclMin1.7.jar b/org.eclipse.jdt.core.tests.model/JCL/jclMin1.7.jar
index 47bbace..fe8e028 100644
--- a/org.eclipse.jdt.core.tests.model/JCL/jclMin1.7.jar
+++ b/org.eclipse.jdt.core.tests.model/JCL/jclMin1.7.jar
Binary files differ
diff --git a/org.eclipse.jdt.core.tests.model/JCL/jclMin1.7src.zip b/org.eclipse.jdt.core.tests.model/JCL/jclMin1.7src.zip
index 411528e..ee3427a 100644
--- a/org.eclipse.jdt.core.tests.model/JCL/jclMin1.7src.zip
+++ b/org.eclipse.jdt.core.tests.model/JCL/jclMin1.7src.zip
Binary files differ
diff --git a/org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF b/org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF
index 78e3efe..e44bbd0 100644
--- a/org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF
@@ -1,7 +1,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.jdt.core.tests.model;singleton:=true
-Bundle-Version: 3.11.100.qualifier
+Bundle-Version: 3.11.200.qualifier
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
 Export-Package: org.eclipse.jdt.core.tests,
diff --git a/org.eclipse.jdt.core.tests.model/pom.xml b/org.eclipse.jdt.core.tests.model/pom.xml
index 11b7913..b9047b8 100644
--- a/org.eclipse.jdt.core.tests.model/pom.xml
+++ b/org.eclipse.jdt.core.tests.model/pom.xml
@@ -15,11 +15,11 @@
   <parent>
     <artifactId>tests-pom</artifactId>
     <groupId>org.eclipse.jdt</groupId>
-    <version>4.23.0-SNAPSHOT</version>
+    <version>4.24.0-SNAPSHOT</version>
     <relativePath>../tests-pom/</relativePath>
   </parent>
   <artifactId>org.eclipse.jdt.core.tests.model</artifactId>
-  <version>3.11.100-SNAPSHOT</version>
+  <version>3.11.200-SNAPSHOT</version>
   <packaging>eclipse-test-plugin</packaging>
 
   <properties>
@@ -265,6 +265,36 @@
 			<tycho.surefire.argLine>--add-modules ALL-SYSTEM -Dcompliance=1.4,1.7,1.8,14,17</tycho.surefire.argLine>
 		</properties>
 	</profile>
+	<profile>
+		<id>test-on-javase-18</id>
+		<build>
+			<plugins>
+				<plugin>
+					<groupId>org.apache.maven.plugins</groupId>
+					<artifactId>maven-toolchains-plugin</artifactId>
+					<version>1.1</version>
+					<executions>
+						<execution>
+							<phase>validate</phase>
+							<goals>
+								<goal>toolchain</goal>
+							</goals>
+						</execution>
+					</executions>
+					<configuration>
+						<toolchains>
+							<jdk>
+								<id>JavaSE-18</id>
+							</jdk>
+						</toolchains>
+					</configuration>
+				</plugin>
+			</plugins>
+		</build>
+		<properties>
+			<tycho.surefire.argLine>--add-modules ALL-SYSTEM -Dcompliance=1.4,1.7,1.8,15,18</tycho.surefire.argLine>
+		</properties>
+	</profile>
   </profiles>
 
 </project>
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterJavadocTest_18.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterJavadocTest_18.java
new file mode 100644
index 0000000..13405ab
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterJavadocTest_18.java
@@ -0,0 +1,1074 @@
+/*******************************************************************************
+ * Copyright (c) 2022 IBM Corporation 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
+ *******************************************************************************/
+package org.eclipse.jdt.core.tests.dom;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.ASTParser;
+import org.eclipse.jdt.core.dom.Comment;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.JavaDocRegion;
+import org.eclipse.jdt.core.dom.Javadoc;
+import org.eclipse.jdt.core.dom.TagElement;
+import org.eclipse.jdt.core.dom.TagProperty;
+import org.eclipse.jdt.core.dom.TextElement;
+import org.eclipse.jdt.internal.compiler.parser.JavadocTagConstants;
+import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
+
+/**
+ * Class to test DOM/AST nodes built for Javadoc comments.
+ *
+ * Most of tests are 'automatic'. It means that to add a new tests, you only need to
+ * create one or several CUs and put them in org.eclipse.jdt.core.model.tests/workspace/Converter/src/javadoc/testXXX
+ * folder and add the corresponding test in this class:
+ * <pre>
+ * public void testXXX() throws JavaModelException {
+ * 	verifyComments("testXXX");
+ * }
+ * </pre>
+ *
+ * Note that when a test fails, the easiest way to debug it is to open
+ * a runtime workbench, create a project 'Converter', delete the default 'src' source folder
+ * and replace it by a linked source to the 'src' folder of org.eclipse.jdt.core.model.tests/workspace/Converter/src
+ * in your workspace.
+ *
+ * Then open the CU on which the test fails in a ASTView and verify the offset/length
+ * of the offending node located at the positions displayed in the console when the test failed...
+ *
+ * Since 3.4, the failing test also provides the comparison between the source of the comment
+ * and the string get from the built DOM/AST nodes in the comment (see {@link ASTConverterJavadocFlattener})
+ * but this may be not enough to see precisely the origin of the problem.
+ */
+@SuppressWarnings({"rawtypes", "unchecked"})
+public class ASTConverterJavadocTest_18 extends ConverterTestSetup {
+
+	// Flag to know whether Converter directory should be copied from org.eclipse.jdt.core.tests.model project
+	static protected boolean COPY_DIR = true;
+
+	// Test counters
+	protected static int[] TEST_COUNTERS = { 0, 0, 0, 0 };
+	// Unicode tests
+	protected static boolean UNICODE = false;
+	// Doc Comment support
+	static final String DOC_COMMENT_SUPPORT = System.getProperty("doc.support");
+	// List of comments read from source of test
+	private static final int LINE_COMMENT = 100;
+	private static final int BLOCK_COMMENT =200;
+	private static final int DOC_COMMENT = 300;
+	List comments = new ArrayList();
+	private String chars;
+	// List of tags contained in each comment read from test source.
+	List allTags = new ArrayList();
+	// tags inhibiting inline tags
+	static final String TAG_CODE = "code";
+	static final String TAG_LITERAL = "literal";
+	// Current compilation unit
+	protected ICompilationUnit sourceUnit;
+	// Test package binding
+	protected boolean resolveBinding = true;
+	protected boolean packageBinding = true;
+	// AST Level
+	protected int astLevel = AST.getJLSLatest();
+	protected int savedLevel;
+	// Debug
+	protected String prefix = "";
+	protected boolean debug = false;
+	protected StringBuffer problems;
+	protected String compilerOption = JavaCore.IGNORE;
+	protected List failures;
+	protected boolean stopOnFailure = true;
+	Map savedOptions = null;
+	protected ICompilationUnit moduleUnit;
+
+	private static String SNIPPET_TAG = '@' + new String(JavadocTagConstants.TAG_SNIPPET);
+
+	/**
+	 * @param name
+	 */
+	public ASTConverterJavadocTest_18(String name) {
+		super(name);
+	}
+
+	public static Test suite() {
+		TestSuite suite = new Suite(ASTConverterJavadocTest_18.class.getName());
+		buildSuite(suite);
+		return suite;
+	}
+
+	public static void buildSuite(TestSuite suite) {
+		Class c = ASTConverterJavadocTest_18.class;
+		Method[] methods = c.getMethods();
+		for (int i = 0, max = methods.length; i < max; i++) {
+			if (methods[i].getName().startsWith("test")) { //$NON-NLS-1$
+				suite.addTest(new ASTConverterJavadocTest_18(methods[i].getName()));
+			}
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.tests.model.AbstractJavaModelTests#copyDirectory(java.io.File, java.io.File)
+	 */
+	@Override
+	protected void copyDirectory(File sourceDir, File targetDir) throws IOException {
+		if (COPY_DIR) {
+			super.copyDirectory(sourceDir, targetDir);
+		} else {
+			targetDir.mkdirs();
+			File sourceFile = new File(sourceDir, ".project");
+			File targetFile = new File(targetDir, ".project");
+			targetFile.createNewFile();
+			copy(sourceFile, targetFile);
+			sourceFile = new File(sourceDir, ".classpath");
+			targetFile = new File(targetDir, ".classpath");
+			targetFile.createNewFile();
+			copy(sourceFile, targetFile);
+		}
+	}
+	/* (non-Javadoc)
+	 * @see junit.framework.TestCase#setUp()
+	 */
+	@Override
+	protected void setUp() throws Exception {
+		super.setUp();
+		TEST_COUNTERS[0]++;
+		this.failures = new ArrayList();
+		this.problems = new StringBuffer();
+		this.workingCopies = null;
+		this.savedLevel = this.astLevel;
+	}
+	/* (non-Javadoc)
+	 * @see junit.framework.TestCase#tearDown()
+	 */
+	@Override
+	protected void tearDown() throws Exception {
+		int size = this.failures.size();
+		String title = size+" positions/bindings were incorrect in "+getName();
+		if (size == 0) {
+			TEST_COUNTERS[1]++;
+		} else if (this.problems.length() > 0) {
+			if (this.debug) {
+				System.out.println("Compilation warnings/errors occured:");
+				System.out.println(this.problems.toString());
+			}
+			TEST_COUNTERS[2]++;
+		} else {
+			TEST_COUNTERS[3]++;
+			System.out.println(title+":");
+			for (int i=0; i<size; i++) {
+				System.out.println("	- "+this.failures.get(i));
+			}
+		}
+//		if (!stopOnFailure) {
+			assertTrue(title, size==0 || this.problems.length() > 0);
+//		}
+		super.tearDown();
+
+		// Restore saved ast level
+		this.astLevel = this.savedLevel;
+	}
+
+	/* (non-Javadoc)
+	 * @see junit.framework.TestCase#tearDown()
+	 */
+	@Override
+	public void tearDownSuite() throws Exception {
+		// put default options on project
+		if (this.currentProject != null && this.savedOptions != null) {
+			this.currentProject.setOptions(this.savedOptions);
+		}
+		super.tearDownSuite();
+		if (TEST_COUNTERS[0] != TEST_COUNTERS[1]) {
+			NumberFormat intFormat = NumberFormat.getInstance();
+			intFormat.setMinimumIntegerDigits(3);
+			intFormat.setMaximumIntegerDigits(3);
+			System.out.println("=====================================");
+			System.out.println(intFormat.format(TEST_COUNTERS[0])+" tests have been executed:");
+			System.out.println("  - "+intFormat.format(TEST_COUNTERS[1])+" tests have been actually executed.");
+			System.out.println("  - "+intFormat.format(TEST_COUNTERS[2])+" tests were skipped due to compilation errors.");
+			System.out.println("  - "+intFormat.format(TEST_COUNTERS[3])+" tests failed.");
+		}
+	}
+
+	@Override
+	public ASTNode runConversion(char[] source, String unitName, IJavaProject project) {
+		ASTParser parser = ASTParser.newParser(this.astLevel);
+		parser.setSource(source);
+		parser.setUnitName(unitName);
+		parser.setProject(project);
+		parser.setResolveBindings(this.resolveBinding);
+		return parser.createAST(null);
+	}
+
+	@Override
+	public ASTNode runConversion(char[] source, String unitName, IJavaProject project, Map options) {
+		if (project == null) {
+			ASTParser parser = ASTParser.newParser(this.astLevel);
+			parser.setSource(source);
+			parser.setUnitName(unitName);
+			parser.setCompilerOptions(options);
+			parser.setResolveBindings(this.resolveBinding);
+			return parser.createAST(null);
+		}
+		return runConversion(source, unitName, project);
+	}
+
+	private char getNextChar(char[] source, int idx) {
+			// get next char
+			char ch = source[idx];
+			int charLength = 1;
+			int pos = idx;
+			this.chars = null;
+			if (ch == '\\' && source[idx+1] == 'u') {
+				//-------------unicode traitement ------------
+				int c1, c2, c3, c4;
+				charLength++;
+				while (source[idx+charLength] == 'u') charLength++;
+				if (((c1 = ScannerHelper.getHexadecimalValue(source[idx+charLength++])) > 15 || c1 < 0)
+					|| ((c2 = ScannerHelper.getHexadecimalValue(source[idx+charLength++])) > 15 || c2 < 0)
+					|| ((c3 = ScannerHelper.getHexadecimalValue(source[idx+charLength++])) > 15 || c3 < 0)
+					|| ((c4 = ScannerHelper.getHexadecimalValue(source[idx+charLength++])) > 15 || c4 < 0)) {
+					return ch;
+				}
+				ch = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+				this.chars = new String(source, pos, charLength);
+			}
+			return ch;
+	}
+	/*
+	 * Convert Javadoc source to match Javadoc.toString().
+	 * Store converted comments and their corresponding tags respectively
+	 * in comments and allTags fields
+	 */
+	protected void setSourceComment(char[] source) throws ArrayIndexOutOfBoundsException {
+		this.comments = new ArrayList();
+		this.allTags = new ArrayList();
+		StringBuilder buffer = null;
+		int comment = 0;
+		boolean end = false, lineStarted = false;
+		String tag = null;
+		List tags = new ArrayList();
+		int length = source.length;
+		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=206345
+		// when parsing tags such as @code and @literal,
+		// any tag should be discarded and considered as plain text until
+		// properly closed with closing brace
+		boolean considerTagAsPlainText = false;
+		int openingBraces = 0;
+		char previousChar=0, currentChar=0;
+		for (int i=0; i<length;) {
+			previousChar = currentChar;
+			// get next char
+			currentChar = getNextChar(source, i);
+			i += (this.chars==null) ? 1 : this.chars.length();
+
+			switch (comment) {
+				case 0:
+					switch (currentChar) {
+						case '/':
+							comment = 1; // first char for comments...
+							buffer = new StringBuilder();
+							if (this.chars == null) buffer.append(currentChar);
+							else buffer.append(this.chars);
+							break;
+						case '\'':
+							while (i<length) {
+								// get next char
+								currentChar = getNextChar(source, i);
+								i += (this.chars==null) ? 1 : this.chars.length();
+								if (currentChar == '\\') {
+									// get next char
+									currentChar = getNextChar(source, i);
+									i += (this.chars==null) ? 1 : this.chars.length();
+								} else {
+									if (currentChar == '\'') {
+										break;
+									}
+								}
+							}
+							break;
+						case '"':
+							while (i<length) {
+								// get next char
+								currentChar = getNextChar(source, i);
+								i += (this.chars==null) ? 1 : this.chars.length();
+								if (currentChar == '\\') {
+									// get next char
+									currentChar = getNextChar(source, i);
+									i += (this.chars==null) ? 1 : this.chars.length();
+								} else {
+									if (currentChar == '"') {
+										// get next char
+										currentChar = getNextChar(source, i);
+										if (currentChar == '"') {
+											i += (this.chars==null) ? 1 : this.chars.length();
+										} else {
+											break;
+										}
+									}
+								}
+							}
+							break;
+					}
+					break;
+				case 1: // first '/' has been found...
+					switch (currentChar) {
+						case '/':
+							if (this.chars == null) buffer.append(currentChar);
+							else buffer.append(this.chars);
+							comment = LINE_COMMENT;
+							break;
+						case '*':
+							if (this.chars == null) buffer.append(currentChar);
+							else buffer.append(this.chars);
+							comment = 2; // next step
+							break;
+						default:
+							comment = 0;
+							break;
+					}
+					break;
+				case 2: // '/*' has been found...
+					if (currentChar == '*') {
+						comment = 3; // next step...
+					} else {
+						comment = BLOCK_COMMENT;
+					}
+					if (this.chars == null) buffer.append(currentChar);
+					else buffer.append(this.chars);
+					break;
+				case 3: // '/**' has bee found, verify that's not an empty block comment
+					if (currentChar == '/') { // empty block comment
+						if (this.chars == null) buffer.append(currentChar);
+						else buffer.append(this.chars);
+						this.comments.add(buffer.toString());
+						this.allTags.add(new ArrayList());
+						comment = 0;
+						break;
+					}
+					comment = DOC_COMMENT;
+					// $FALL-THROUGH$ - do not break, directly go to next case...
+				case DOC_COMMENT:
+					if (tag != null) { // a tag name is currently scanned
+						if (currentChar >= 'a' && currentChar <= 'z') {
+							tag += currentChar;
+						} else {
+							if (tag.equalsIgnoreCase(TAG_LITERAL) || tag.equalsIgnoreCase(TAG_CODE)) considerTagAsPlainText = true;
+							tags.add(tag);
+							tag = null;
+						}
+					}
+					// Some characters are special in javadoc comments
+					switch (currentChar) {
+						case '@':
+							if (!lineStarted) {
+								tag = "";
+								lineStarted = true;
+							} else if (previousChar == '{') {
+								// https://bugs.eclipse.org/bugs/show_bug.cgi?id=206345
+								if (considerTagAsPlainText) {
+									openingBraces++;
+								} else {
+									tag = "";
+									lineStarted = true;
+								}
+							}
+							break;
+						case '\r':
+						case '\n':
+							lineStarted = false;
+							break;
+						case '*':
+							break;
+						case '}':
+							// https://bugs.eclipse.org/bugs/show_bug.cgi?id=206345
+							if (considerTagAsPlainText) {
+								if (openingBraces > 0) {
+									openingBraces--;
+								} else {
+									considerTagAsPlainText = false;
+								}
+							}
+							break;
+						default:
+							if (!Character.isWhitespace(currentChar)) {
+								lineStarted = true;
+							}
+					}
+					// $FALL-THROUGH$ - common treatment for block and javadoc comments
+				case BLOCK_COMMENT:
+					if (this.chars == null) buffer.append(currentChar);
+					else buffer.append(this.chars);
+					if (end && currentChar == '/') {
+						comment = 0;
+						lineStarted = false;
+						this.comments.add(buffer.toString());
+						this.allTags.add(tags);
+						tags = new ArrayList();
+					}
+					end = currentChar == '*';
+					break;
+				case LINE_COMMENT:
+					if (currentChar == '\r' || currentChar == '\n') {
+						/*
+						if (currentChar == '\r' && source[i+1] == '\n') {
+							buffer.append(source[++i]);
+						}
+						*/
+						comment = 0;
+						this.comments.add(buffer.toString());
+						this.allTags.add(tags);
+					} else {
+						if (this.chars == null) buffer.append(currentChar);
+						else buffer.append(this.chars);
+					}
+					break;
+				default:
+					// do nothing
+					break;
+			}
+		}
+	}
+
+	/*
+	 * Convert Javadoc source to match Javadoc.toString().
+	 * Store converted comments and their corresponding tags respectively
+	 * in comments and allTags fields
+	 */
+	char[] getUnicodeSource(char[] source) {
+		int length = source.length;
+		int unicodeLength = length*6;
+		char[] unicodeSource = new char[unicodeLength];
+		int u=0;
+		for (int i=0; i<length; i++) {
+			// get next char
+			if (source[i] == '\\' && source[i+1] == 'u') {
+				//-------------unicode traitement ------------
+				int c1, c2, c3, c4;
+				unicodeSource[u++] = source[i];
+				unicodeSource[u++] = source[++i];
+				if (((c1 = ScannerHelper.getHexadecimalValue(source[i+1])) > 15 || c1 < 0)
+					|| ((c2 = ScannerHelper.getHexadecimalValue(source[i+2])) > 15 || c2 < 0)
+					|| ((c3 = ScannerHelper.getHexadecimalValue(source[i+3])) > 15 || c3 < 0)
+					|| ((c4 = ScannerHelper.getHexadecimalValue(source[i+4])) > 15 || c4 < 0)) {
+					throw new RuntimeException("Invalid unicode in source at "+i);
+				}
+				for (int j=0; j<4; j++) unicodeSource[u++] = source[++i];
+			} else {
+				unicodeSource[u++] = '\\';
+				unicodeSource[u++] = 'u';
+				unicodeSource[u++] = '0';
+				unicodeSource[u++] = '0';
+				int val = source[i]/16;
+				unicodeSource[u++] = (char) (val<10 ? val+ 0x30 : val-10+0x61);
+				val = source[i]%16;
+				unicodeSource[u++] = (char) (val<10 ? val+ 0x30 : val-10+0x61);
+			}
+		}
+		// Return one well sized array
+		if (u != unicodeLength) {
+			char[] result = new char[u];
+			System.arraycopy(unicodeSource, 0, result, 0, u);
+			return result;
+		}
+		return unicodeSource;
+	}
+
+	/*
+	 * Convert Javadoc source to match Javadoc.toString().
+	 * Store converted comments and their corresponding tags respectively
+	 * in comments and allTags fields
+	 */
+	char[] getUnixSource(char[] source) {
+		int length = source.length;
+		int unixLength = length;
+		char[] unixSource = new char[unixLength];
+		int u=0;
+		for (int i=0; i<length; i++) {
+			// get next char
+			if (source[i] == '\r' && source[i+1] == '\n') {
+				i++;
+			}
+			unixSource[u++] = source[i];
+		}
+		// Return one well sized array
+		if (u != unixLength) {
+			char[] result = new char[u];
+			System.arraycopy(unixSource, 0, result, 0, u);
+			return result;
+		}
+		return unixSource;
+	}
+
+	/*
+	 * Return all tags number for a given Javadoc
+	 */
+	int allTags(Javadoc docComment) {
+		int all = 0;
+		// Count main tags
+		Iterator tags = docComment.tags().listIterator();
+		while (tags.hasNext()) {
+			TagElement tagElement = (TagElement) tags.next();
+			if (tagElement.getTagName() != null) {
+				all++;
+			}
+			Iterator fragments = tagElement.fragments().listIterator();
+			while (fragments.hasNext()) {
+				ASTNode node = (ASTNode) fragments.next();
+				if (node.getNodeType() == ASTNode.TAG_ELEMENT) {
+					all++;
+				}
+			}
+		}
+		return all;
+	}
+
+	/*
+	 * Add a failure to the list. Use only one method as it easier to put breakpoint to
+	 * debug failure when it occurs...
+	 */
+	private void addFailure(String msg) {
+		this.failures.add(msg);
+	}
+
+	/*
+	 * Put the failure message in list instead of throwing exception immediately.
+	 * This allow to store several failures per test...
+	 * @see tearDown method which finally throws the execption to signal that test fails.
+	 */
+	protected void assumeTrue(String msg, boolean cond) {
+		if (!cond) {
+			addFailure(msg);
+			if (this.stopOnFailure) assertTrue(msg, cond);
+		}
+	}
+
+	/*
+	 * Put the failure message in list instead of throwing exception immediately.
+	 * This allow to store several failures per test...
+	 * @see tearDown method which finally throws the execption to signal that test fails.
+	 */
+	protected void assumeNull(String msg, Object obj) {
+		if (obj != null) {
+			addFailure(msg);
+			if (this.stopOnFailure) assertNull(msg, obj);
+		}
+	}
+
+	/*
+	 * Put the failure message in list instead of throwing exception immediately.
+	 * This allow to store several failures per test...
+	 * @see tearDown method which finally throws the execption to signal that test fails.
+	 */
+	protected void assumeNotNull(String msg, Object obj) {
+		if (obj == null) {
+			addFailure(msg);
+			if (this.stopOnFailure) assertNotNull(msg, obj);
+		}
+	}
+
+	/*
+	 * Put the failure message in list instead of throwing exception immediately.
+	 * This allow to store several failures per test...
+	 * @see tearDown method which finally throws the execption to signal that test fails.
+	 */
+	protected void assumeEquals(String msg, int expected, int actual) {
+		if (expected != actual) {
+			addFailure(msg+", expected="+expected+" actual="+actual);
+			if (this.stopOnFailure) assertEquals(msg, expected, actual);
+		}
+	}
+
+	/*
+	 * Put the failure message in list instead of throwing exception immediately.
+	 * This allow to store several failures per test...
+	 * @see tearDown method which finally throws the execption to signal that test fails.
+	 */
+	protected void assumeEquals(String msg, Object expected, Object actual) {
+		if (expected == null && actual == null)
+			return;
+		if (expected != null && expected.equals(actual))
+			return;
+		addFailure(msg+", expected:<"+expected+"> actual:<"+actual+'>');
+		if (this.stopOnFailure) assertEquals(msg, expected, actual);
+	}
+
+	/* (non-Javadoc)
+	 * @see junit.framework.TestCase#setUp()
+	 */
+	protected void verifyComments(String test) throws JavaModelException {
+		ICompilationUnit[] units = getCompilationUnits("Converter" , "src", "javadoc."+test); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		for (int i=0; i<units.length; i++) {
+			verifyComments(units[i]);
+		}
+	}
+
+	/*
+	 * Verify the comments of a compilation unit.
+	 */
+	protected void verifyWorkingCopiesComments() throws JavaModelException {
+		assumeNotNull("No working copies to verify!", this.workingCopies);
+		int length = this.workingCopies.length;
+		assumeTrue("We need to have at least one working copy to verify!", length>0);
+		for (int i=0; i<length; i++) {
+			verifyComments(this.workingCopies[i]);
+		}
+	}
+
+	/*
+	 * Verify the comments of a compilation unit.
+	 */
+	protected CompilationUnit verifyComments(ICompilationUnit unit) throws JavaModelException {
+		// Get test file
+		this.sourceUnit = unit;
+		this.prefix = unit.getElementName()+": ";
+
+		// Get current project
+		String sourceStr = this.sourceUnit.getSource();
+		if (this.savedOptions != null && !this.sourceUnit.getJavaProject().getElementName().equals(this.currentProject.getElementName())) {
+			this.currentProject.setOptions(this.savedOptions);
+			this.savedOptions = null;
+		}
+		this.currentProject = this.sourceUnit.getJavaProject();
+		if (this.savedOptions == null) this.savedOptions = this.currentProject.getOptions(false);
+
+		// set up java project options
+		this.currentProject.setOption(JavaCore.COMPILER_PB_INVALID_JAVADOC, this.compilerOption);
+		this.currentProject.setOption(JavaCore.COMPILER_PB_MISSING_JAVADOC_TAGS, this.compilerOption);
+		this.currentProject.setOption(JavaCore.COMPILER_PB_MISSING_JAVADOC_COMMENTS, this.compilerOption);
+		this.currentProject.setOption(JavaCore.COMPILER_PB_METHOD_WITH_CONSTRUCTOR_NAME, JavaCore.IGNORE);
+		this.currentProject.setOption(JavaCore.COMPILER_DOC_COMMENT_SUPPORT, JavaCore.ENABLED);
+
+		// Verify source regardings converted comments
+		char[] source = sourceStr.toCharArray();
+		String fileName = unit.getPath().toString();
+		try {
+			return verifyComments(fileName, source);
+		}
+		catch (RuntimeException ex) {
+			TEST_COUNTERS[3]++;
+			throw ex;
+		}
+	}
+
+	protected CompilationUnit verifyComments(String fileName, char[] source) {
+		return verifyComments(fileName, source, null);
+	}
+
+	protected CompilationUnit verifyComments(String fileName, char[] source, Map options) {
+
+		// Verify comments either in unicode or not
+		char[] testedSource = source;
+		if (UNICODE) {
+			testedSource = getUnicodeSource(source);
+		}
+
+		// Get comments infos from test file
+		setSourceComment(testedSource);
+
+		// Create DOM AST nodes hierarchy
+		List unitComments = null;
+		String sourceLevel = null;
+		String complianceLevel = null;
+		if (this.currentProject != null) {
+			complianceLevel = this.currentProject.getOption(JavaCore.COMPILER_COMPLIANCE, true);
+			sourceLevel = this.currentProject.getOption(JavaCore.COMPILER_SOURCE, true);
+			this.currentProject.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_18);
+			this.currentProject.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_18);
+		}
+		CompilationUnit compilUnit = (CompilationUnit) runConversion(testedSource, fileName, this.currentProject, options);
+		if (this.compilerOption.equals(JavaCore.ERROR)) {
+			assumeEquals(this.prefix+"Unexpected problems", 0, compilUnit.getProblems().length); //$NON-NLS-1$
+		} else if (this.compilerOption.equals(JavaCore.WARNING)) {
+			IProblem[] problemsList = compilUnit.getProblems();
+			int length = problemsList.length;
+			if (length > 0) {
+				this.problems.append("  - "+this.prefix+length+" problems:"); //$NON-NLS-1$
+				for (int i = 0; i < problemsList.length; i++) {
+					this.problems.append("	+ ");
+					this.problems.append(problemsList[i]);
+					this.problems.append("\n");
+				}
+			}
+		}
+		unitComments = compilUnit.getCommentList();
+		assumeNotNull(this.prefix+"Unexpected problems", unitComments);
+
+		// Basic comments verification
+		int size = unitComments.size();
+		assumeEquals(this.prefix+"Wrong number of comments!", this.comments.size(), size);
+
+		// Verify comments positions and bindings
+		for (int i=0; i<size; i++) {
+			Comment comment = (Comment) unitComments.get(i);
+			List tags = (List) this.allTags.get(i);
+			// Verify flattened content
+			String stringComment = (String) this.comments.get(i);
+//			ASTConverterJavadocFlattener printer = new ASTConverterJavadocFlattener(stringComment);
+//			comment.accept(printer);
+			String text = new String(testedSource, comment.getStartPosition(), comment.getLength());
+			assumeEquals(this.prefix+"Flattened comment does NOT match source!", stringComment, text);
+			// Verify javdoc tags positions and bindings
+			if (comment.isDocComment()) {
+				Javadoc docComment = (Javadoc)comment;
+				assumeEquals(this.prefix+"Invalid tags number in javadoc:\n"+docComment+"\n", tags.size(), allTags(docComment));
+			}
+		}
+
+		/* Verify each javadoc: not implemented yet
+		Iterator types = compilUnit.types().listIterator();
+		while (types.hasNext()) {
+			TypeDeclaration typeDeclaration = (TypeDeclaration) types.next();
+			verifyJavadoc(typeDeclaration.getJavadoc());
+		}
+		*/
+
+		if (sourceLevel != null) {
+			this.currentProject.setOption(JavaCore.COMPILER_COMPLIANCE, complianceLevel);
+			this.currentProject.setOption(JavaCore.COMPILER_SOURCE, sourceLevel);
+		}
+		// Return compilation unit for possible further verifications
+		return compilUnit;
+	}
+
+	private TagElement getSnippetTag(Javadoc docComment) {
+		TagElement snippet = null;
+		if (docComment != null) {
+			for (Object tag : docComment.tags()) {
+				if (tag instanceof TagElement) {
+					TagElement tagElement = (TagElement) tag;
+					if (SNIPPET_TAG.equals(tagElement.getTagName())) {
+						return tagElement;
+					}
+					List fragments = tagElement.fragments();
+					for (Object fragment : fragments) {
+						if (fragment instanceof TagElement) {
+							TagElement tagElem = (TagElement) fragment;
+							if (SNIPPET_TAG.equals(tagElem.getTagName())) {
+								return tagElem;
+							}
+						}
+					}
+
+				}
+			}
+		}
+		return snippet;
+	}
+
+	public void testSnippetStartJavadoc1() throws JavaModelException {
+		this.workingCopies = new ICompilationUnit[1];
+		this.workingCopies[0] = getWorkingCopy("/Converter_15_1/src/javadoc/X.java",
+			"package javadoc;\n" +
+			"public class X {\n" +
+			"    /**\n" +
+			"     * Below is an example snippet\n" +
+			"     * {@snippet :\n" +
+			"     *  System.out.println(); \n" +
+			"     * }\n" +
+			"     */\n" +
+			"    public static void foo(Object object) {\n" +
+			"    }\n" +
+			"}\n"
+		);
+		CompilationUnit compilUnit = verifyComments(this.workingCopies[0]);
+		// Get comments
+		List unitComments = compilUnit.getCommentList();
+		int size = unitComments.size();
+		assertEquals("Wrong number of comments", 1, size);
+		Javadoc javadoc = (Javadoc) unitComments.get(0);
+		TagElement snippetTag = getSnippetTag(javadoc);
+		assertNotNull("Snippet Tag is not present", snippetTag);
+		Object validPorperty = snippetTag.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_IS_VALID);
+		assertNotNull("Snippet Tag valid property not present", validPorperty);
+		assertEquals("Snippet should be valid", true, (validPorperty instanceof Boolean) ? ((Boolean)validPorperty).booleanValue() : false);
+	}
+
+	public void testSnippetStartJavadoc2() throws JavaModelException {
+		this.workingCopies = new ICompilationUnit[1];
+		this.workingCopies[0] = getWorkingCopy("/Converter_15_1/src/javadoc/X.java",
+			"package javadoc;\n" +
+			"public class X {\n" +
+			"    /**\n" +
+			"     * Below is an example snippet\n" +
+			"     * {@snippet \n" +
+			"	  * \n" +
+			"	  *		\n" +
+			"	  *			\n" +
+			"	  *\n" +
+			"	  *	:\n" +
+			"     *  System.out.println(); \n" +
+			"     * }\n" +
+			"     */\n" +
+			"    public static void foo(Object object) {\n" +
+			"    }\n" +
+			"}\n"
+		);
+		CompilationUnit compilUnit = verifyComments(this.workingCopies[0]);
+		// Get comments
+		List unitComments = compilUnit.getCommentList();
+		int size = unitComments.size();
+		assertEquals("Wrong number of comments", 1, size);
+		Javadoc javadoc = (Javadoc) unitComments.get(0);
+		TagElement snippetTag = getSnippetTag(javadoc);
+		assertNotNull("Snippet Tag is not present", snippetTag);
+		Object validPorperty = snippetTag.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_IS_VALID);
+		assertNotNull("Snippet Tag valid property not present", validPorperty);
+		assertEquals("Snippet should be valid", true, (validPorperty instanceof Boolean) ? ((Boolean)validPorperty).booleanValue() : false);
+	}
+
+	public void testSnippetStartJavadoc3() throws JavaModelException {
+		this.workingCopies = new ICompilationUnit[1];
+		this.workingCopies[0] = getWorkingCopy("/Converter_15_1/src/javadoc/X.java",
+			"package javadoc;\n" +
+			"public class X {\n" +
+			"    /**\n" +
+			"     * Below is an example snippet\n" +
+			"     * {@snippet \n" +
+			"	  * \n" +
+			"	  *		\n" +
+			"	  			\n" +
+			"	  *\n" +
+			"	  *	:\n" +
+			"     *  System.out.println(); \n" +
+			"     * }\n" +
+			"     */\n" +
+			"    public static void foo(Object object) {\n" +
+			"    }\n" +
+			"}\n"
+		);
+		CompilationUnit compilUnit = verifyComments(this.workingCopies[0]);
+		// Get comments
+		List unitComments = compilUnit.getCommentList();
+		int size = unitComments.size();
+		assertEquals("Wrong number of comments", 1, size);
+		Javadoc javadoc = (Javadoc) unitComments.get(0);
+		TagElement snippetTag = getSnippetTag(javadoc);
+		assertNotNull("Snippet Tag is not present", snippetTag);
+		Object validPorperty = snippetTag.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_IS_VALID);
+		assertNotNull("Snippet Tag valid property not present", validPorperty);
+		assertEquals("Snippet should be valid", true, (validPorperty instanceof Boolean) ? ((Boolean)validPorperty).booleanValue() : false);
+	}
+
+	public void testSnippetStartJavadoc4() throws JavaModelException {
+		this.workingCopies = new ICompilationUnit[1];
+		this.workingCopies[0] = getWorkingCopy("/Converter_15_1/src/javadoc/X.java",
+			"package javadoc;\n" +
+			"public class X {\n" +
+			"    /**\n" +
+			"     * Below is an example snippet\n" +
+			"     * {@snippet \n" +
+			"	  * \n" +
+			"	  *		\n" +
+			"	  			\n" +
+			"	  *\n" +
+			"	  *	: a\n" +
+			"     *  System.out.println(); \n" +
+			"     * }\n" +
+			"     */\n" +
+			"    public static void foo(Object object) {\n" +
+			"    }\n" +
+			"}\n"
+		);
+		CompilationUnit compilUnit = verifyComments(this.workingCopies[0]);
+		// Get comments
+		List unitComments = compilUnit.getCommentList();
+		int size = unitComments.size();
+		assertEquals("Wrong number of comments", 1, size);
+		Javadoc javadoc = (Javadoc) unitComments.get(0);
+		TagElement snippetTag = getSnippetTag(javadoc);
+		assertNotNull("Snippet Tag is not present", snippetTag);
+		Object validPorperty = snippetTag.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_IS_VALID);
+		assertNotNull("Snippet Tag valid property not present", validPorperty);
+		assertEquals("Snippet should not be valid", false, (validPorperty instanceof Boolean) ? ((Boolean)validPorperty).booleanValue() : false);
+	}
+
+	public void testSnippetMultiLineTagsJavadoc1() throws JavaModelException {
+		this.workingCopies = new ICompilationUnit[1];
+		this.workingCopies[0] = getWorkingCopy("/Converter_15_1/src/javadoc/X.java",
+			"package javadoc;\n" +
+			"public class X {\n" +
+			"    /**\n" +
+			"     * Below is an example snippet\n" +
+			"     * {@snippet :\n" +
+			"     *  //Starting Code // @highlight substring=\"out\" :\n" +
+			"     *  System.out.println(); // @highlight substring=\"print\"\n" +
+			"     * }\n" +
+			"     */\n" +
+			"    public static void foo(Object object) {\n" +
+			"    }\n" +
+			"}\n"
+		);
+		CompilationUnit compilUnit = verifyComments(this.workingCopies[0]);
+		// Get comments
+		List unitComments = compilUnit.getCommentList();
+		int size = unitComments.size();
+		assertEquals("Wrong number of comments", 1, size);
+		Javadoc javadoc = (Javadoc) unitComments.get(0);
+		TagElement snippetTag = getSnippetTag(javadoc);
+		assertNotNull("Snippet Tag is not present", snippetTag);
+		Object validPorperty = snippetTag.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_IS_VALID);
+		assertNotNull("Snippet Tag valid property not present", validPorperty);
+		assertEquals("Snippet should be valid", true, (validPorperty instanceof Boolean) ? ((Boolean)validPorperty).booleanValue() : false);
+		List fragments = snippetTag.fragments();
+		assertEquals("Three fragments should be created", 3, fragments.size());
+		assertEquals("First Tag should be TextElement", true, fragments.get(0) instanceof TextElement);
+		assertEquals("Second Tag should be JavaDocRegion", true, fragments.get(1) instanceof JavaDocRegion);
+		JavaDocRegion region = (JavaDocRegion) fragments.get(1);
+		assertEquals("JavaDocRegion should be dummy", true, region.isDummyRegion());
+		assertEquals("third Tag should be TextElement", true, fragments.get(2) instanceof TextElement);
+		assertEquals("JavaDocRegion should have 2 tags", 2, region.tags().size());
+		assertEquals("JavaDocRegion should have 1 text fragmwent", 1, region.fragments().size());
+	}
+
+	public void testSnippetMultiLineTagsJavadoc2() throws JavaModelException {
+		this.workingCopies = new ICompilationUnit[1];
+		this.workingCopies[0] = getWorkingCopy("/Converter_15_1/src/javadoc/X.java",
+			"package javadoc;\n" +
+			"public class X {\n" +
+			"    /**\n" +
+			"     * Below is an example snippet\n" +
+			"     * {@snippet :\n" +
+			"     *  //Starting Code // @highlight substring=\"out\" @highlight substring=\"Sys\" :\n" +
+			"     *  System.out.println(); // @highlight substring=\"print\"\n" +
+			"     * }\n" +
+			"     */\n" +
+			"    public static void foo(Object object) {\n" +
+			"    }\n" +
+			"}\n"
+		);
+		CompilationUnit compilUnit = verifyComments(this.workingCopies[0]);
+		// Get comments
+		List unitComments = compilUnit.getCommentList();
+		int size = unitComments.size();
+		assertEquals("Wrong number of comments", 1, size);
+		Javadoc javadoc = (Javadoc) unitComments.get(0);
+		TagElement snippetTag = getSnippetTag(javadoc);
+		assertNotNull("Snippet Tag is not present", snippetTag);
+		Object validPorperty = snippetTag.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_IS_VALID);
+		assertNotNull("Snippet Tag valid property not present", validPorperty);
+		assertEquals("Snippet should be valid", true, (validPorperty instanceof Boolean) ? ((Boolean)validPorperty).booleanValue() : false);
+		List fragments = snippetTag.fragments();
+		assertEquals("Three fragments should be created", 3, fragments.size());
+		assertEquals("First Tag should be TextElement", true, fragments.get(0) instanceof TextElement);
+		assertEquals("Second Tag should be JavaDocRegion", true, fragments.get(1) instanceof JavaDocRegion);
+		JavaDocRegion region = (JavaDocRegion) fragments.get(1);
+		assertEquals("JavaDocRegion should be dummy", true, region.isDummyRegion());
+		assertEquals("third Tag should be TextElement", true, fragments.get(2) instanceof TextElement);
+		assertEquals("JavaDocRegion should have 3 tags", 3, region.tags().size());
+		assertEquals("JavaDocRegion should have 1 text fragmwent", 1, region.fragments().size());
+	}
+
+	public void testSnippetMultiLineTagsJavadoc3() throws JavaModelException {
+		this.workingCopies = new ICompilationUnit[1];
+		this.workingCopies[0] = getWorkingCopy("/Converter_15_1/src/javadoc/X.java",
+			"package javadoc;\n" +
+			"public class X {\n" +
+			"    /**\n" +
+			"     * Below is an example snippet\n" +
+			"     * {@snippet :\n" +
+			"     *  //Starting Code // @highlight region substring=\"out\" :\n" +
+			"     *  System.out.println(); // @highlight substring=\"print\" @end\n" +
+			"     * }\n" +
+			"     */\n" +
+			"    public static void foo(Object object) {\n" +
+			"    }\n" +
+			"}\n"
+		);
+		CompilationUnit compilUnit = verifyComments(this.workingCopies[0]);
+		// Get comments
+		List unitComments = compilUnit.getCommentList();
+		int size = unitComments.size();
+		assertEquals("Wrong number of comments", 1, size);
+		Javadoc javadoc = (Javadoc) unitComments.get(0);
+		TagElement snippetTag = getSnippetTag(javadoc);
+		assertNotNull("Snippet Tag is not present", snippetTag);
+		Object validPorperty = snippetTag.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_IS_VALID);
+		assertNotNull("Snippet Tag valid property not present", validPorperty);
+		assertEquals("Snippet should be valid", true, (validPorperty instanceof Boolean) ? ((Boolean)validPorperty).booleanValue() : false);
+		List fragments = snippetTag.fragments();
+		assertEquals("Four fragments should be created", 4, fragments.size());
+		assertEquals("First Tag should be TextElement", true, fragments.get(0) instanceof TextElement);
+		assertEquals("Second Tag should be JavaDocRegion", true, fragments.get(1) instanceof JavaDocRegion);
+		JavaDocRegion region = (JavaDocRegion) fragments.get(1);
+		assertEquals("JavaDocRegion should be dummy", false, region.isDummyRegion());
+		assertEquals("third Tag should be TextElement", true, fragments.get(2) instanceof TagElement);
+		TagElement tagElem = (TagElement) fragments.get(2);
+		assertEquals("third Tag should be TextElement", true, fragments.get(3) instanceof TextElement);
+		assertEquals("TagElement should have 1 fragment", 1, tagElem.fragments().size());
+		assertEquals("Tag element fragment should be TextElement", true, tagElem.fragments().get(0) instanceof TextElement);
+		TextElement textElem =  (TextElement) tagElem.fragments().get(0);
+		List<JavaDocRegion> regions = snippetTag.tagRegionsContainingTextElement(textElem);
+		assertEquals("regions count should be 1", 1, regions.size());
+		assertEquals("original JavaDocRegion should be present here", true, regions.contains(region));
+	}
+
+	public void testSnippetMultiLineTagsJavadoc4() throws JavaModelException {
+		this.workingCopies = new ICompilationUnit[1];
+		this.workingCopies[0] = getWorkingCopy("/Converter_15_1/src/javadoc/X.java",
+			"package javadoc;\n" +
+			"public class X {\n" +
+			"    /**\n" +
+			"     * Below is an example snippet\n" +
+			"     * {@snippet :\n" +
+			"     *  //Starting Code // @highlight substring=\"out\" :\n" +
+			"     *  System.out.println(); // @highlight substring=\"print\" :\n" +
+			"     *  System.out.println();\n" +
+			"     * }\n" +
+			"     */\n" +
+			"    public static void foo(Object object) {\n" +
+			"    }\n" +
+			"}\n"
+		);
+		CompilationUnit compilUnit = verifyComments(this.workingCopies[0]);
+		// Get comments
+		List unitComments = compilUnit.getCommentList();
+		int size = unitComments.size();
+		assertEquals("Wrong number of comments", 1, size);
+		Javadoc javadoc = (Javadoc) unitComments.get(0);
+		TagElement snippetTag = getSnippetTag(javadoc);
+		assertNotNull("Snippet Tag is not present", snippetTag);
+		Object validPorperty = snippetTag.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_IS_VALID);
+		assertNotNull("Snippet Tag valid property not present", validPorperty);
+		assertEquals("Snippet should be valid", true, (validPorperty instanceof Boolean) ? ((Boolean)validPorperty).booleanValue() : false);
+		List fragments = snippetTag.fragments();
+		assertEquals("Four fragments should be created", 4, fragments.size());
+		assertEquals("First fragment should be TextElement", true, fragments.get(0) instanceof TextElement);
+		assertEquals("Second fragment should be TagElement", true, fragments.get(1) instanceof TagElement);
+		TagElement tagElem = (TagElement) fragments.get(1);
+		assertEquals("TagElement should have 1 fragment", 1, tagElem.fragments().size());
+		assertEquals("Tag element fragment should be TextElement", true, tagElem.fragments().get(0) instanceof TextElement);
+		assertEquals("Third fragment should be TagElement", true, fragments.get(1) instanceof TagElement);
+		tagElem = (TagElement) fragments.get(2);
+		assertEquals("TagElement should have 1 fragment", 1, tagElem.fragments().size());
+		assertEquals("Tag element fragment should be TextElement", true, tagElem.fragments().get(0) instanceof TextElement);
+		assertEquals("Fourth fragment should be TextElement", true, fragments.get(3) instanceof TextElement);
+	}
+}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter_17Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter_17Test.java
index 8edd4b0..a4fcd08 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter_17Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter_17Test.java
@@ -1,11 +1,10 @@
 /*******************************************************************************
- * Copyright (c) 2021 IBM Corporation and others.
+ * Copyright (c) 2021, 2022 IBM Corporation 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
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -30,6 +29,7 @@
 
 	ICompilationUnit workingCopy;
 
+	@SuppressWarnings("deprecation")
 	public void setUpSuite() throws Exception {
 		super.setUpSuite();
 		this.ast = AST.newAST(getAST17(), false);
@@ -50,6 +50,7 @@
 		return buildModelTestSuite(ASTConverter_17Test.class);
 	}
 
+	@SuppressWarnings("deprecation")
 	static int getAST17() {
 		return AST.JLS17;
 	}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter_PreviewTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter_PreviewTest.java
index 11b93ed..1422aca 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter_PreviewTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter_PreviewTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2020, 2021 IBM Corporation and others.
+ * Copyright (c) 2020, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -8,6 +8,7 @@
  *
  * SPDX-License-Identifier: EPL-2.0
  *
+ * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
 package org.eclipse.jdt.core.tests.dom;
@@ -45,10 +46,10 @@
 		super.setUpSuite();
 		this.ast = AST.newAST(getASTLatest(), false);
 		this.currentProject = getJavaProject("Converter_17");
-		if (this.ast.apiLevel() == AST.JLS17) {
-			this.currentProject.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_17);
-			this.currentProject.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_17);
-			this.currentProject.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_17);
+		if (this.ast.apiLevel() == AST.JLS18) {
+			this.currentProject.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_18);
+			this.currentProject.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_18);
+			this.currentProject.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_18);
 			this.currentProject.setOption(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES, JavaCore.ENABLED);
 			this.currentProject.setOption(JavaCore.COMPILER_PB_REPORT_PREVIEW_FEATURES, JavaCore.IGNORE);
 
@@ -64,7 +65,7 @@
 	}
 
 	static int getASTLatest() {
-		return AST.JLS17;
+		return AST.getJLSLatest();
 	}
 	protected void tearDown() throws Exception {
 		super.tearDown();
@@ -75,12 +76,12 @@
 	}
 
 	private void printJREError() {
-		System.err.println("Test "+getName()+" requires a JRE 17");
+		System.err.println("Test "+getName()+" requires a JRE 18");
 	}
 
 	@SuppressWarnings("rawtypes")
 	public void testTypePattern() throws CoreException {
-		if (!isJRE17) {
+		if (!isJRE18) {
 			printJREError();
 			return;
 		}
@@ -128,7 +129,7 @@
 
 	@SuppressWarnings("rawtypes")
 	public void testGuardedPattern() throws CoreException {
-		if (!isJRE17) {
+		if (!isJRE18) {
 			printJREError();
 			return;
 		}
@@ -184,7 +185,7 @@
 
 	@SuppressWarnings("rawtypes")
 	public void testParenthesizedExpressionPattern() throws CoreException {
-		if (!isJRE17) {
+		if (!isJRE18) {
 			printJREError();
 			return;
 		}
@@ -225,7 +226,7 @@
 
 	@SuppressWarnings("rawtypes")
 	public void testNullPattern() throws CoreException {
-		if (!isJRE17) {
+		if (!isJRE18) {
 			printJREError();
 			return;
 		}
@@ -258,7 +259,7 @@
 
 	@SuppressWarnings("rawtypes")
 	public void testCaseDefaultExpressionPattern() throws CoreException {
-		if (!isJRE17) {
+		if (!isJRE18) {
 			printJREError();
 			return;
 		}
@@ -290,8 +291,8 @@
 	}
 
 	public void testBug575250() throws CoreException {
-		if (!isJRE17) {
-			System.err.println("Test "+getName()+" requires a JRE 17");
+		if (!isJRE18) {
+			System.err.println("Test "+getName()+" requires a JRE 18");
 			return;
 		}
 		String contents = "public class X {\n" +
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTTest.java
index 5a19124..5c47af1 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2021 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -1332,6 +1332,8 @@
         case JavaCore.VERSION_14: return AST.JLS14;
         case JavaCore.VERSION_15: return AST.JLS15;
         case JavaCore.VERSION_16: return AST.JLS16;
+        case JavaCore.VERSION_17: return AST.JLS17;
+        case JavaCore.VERSION_18: return AST.JLS18;
         default:  return AST.JLS2;
 		}
 	}
@@ -9506,6 +9508,8 @@
 			ASTNode.GUARDED_PATTERN,
 			ASTNode.NULL_PATTERN,
 			ASTNode.CASE_DEFAULT_EXPRESSION,
+			ASTNode.TAG_PROPERTY,
+			ASTNode.JAVADOC_REGION,
 //{ObjectTeams:
 			ASTNode.METHOD_SPEC,
 			ASTNode.CALLIN_MAPPING_DECLARATION,
@@ -9575,7 +9579,7 @@
 
 	@SuppressWarnings("deprecation")
 	public void testASTLevels() throws Exception {
-		int[] apilLevels = {AST.JLS2, AST.JLS3, AST.JLS4, AST.JLS8, AST.JLS9, AST.JLS10, AST.JLS11, AST.JLS12, AST.JLS13, AST.JLS14, AST.JLS15, AST.JLS16, AST.JLS17};
+		int[] apilLevels = {AST.JLS2, AST.JLS3, AST.JLS4, AST.JLS8, AST.JLS9, AST.JLS10, AST.JLS11, AST.JLS12, AST.JLS13, AST.JLS14, AST.JLS15, AST.JLS16, AST.JLS17,AST.JLS18};
 		for (int level : apilLevels) {
 			try {
 				DOMASTUtil.checkASTLevel(level);
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/AbstractASTTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/AbstractASTTests.java
index 44107f7..b8e4457 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/AbstractASTTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/AbstractASTTests.java
@@ -7,6 +7,7 @@
  * https://www.eclipse.org/legal/epl-2.0/
  *
  * SPDX-License-Identifier: EPL-2.0
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -493,7 +494,9 @@
 		String option = cu.getJavaProject().getOption(JavaCore.COMPILER_COMPLIANCE, true);
 		long jdkLevel = CompilerOptions.versionToJdkLevel(option);
 		int JLSLevel = AST_INTERNAL_JLS3;
-		if (jdkLevel >= ClassFileConstants.getComplianceLevelForJavaVersion(ClassFileConstants.MAJOR_VERSION_17)) {
+		if (jdkLevel >= ClassFileConstants.getComplianceLevelForJavaVersion(ClassFileConstants.MAJOR_VERSION_18)) {
+			JLSLevel = AST_INTERNAL_JLS18;
+		} else if (jdkLevel >= ClassFileConstants.getComplianceLevelForJavaVersion(ClassFileConstants.MAJOR_VERSION_17)) {
 			JLSLevel = AST_INTERNAL_JLS17;
 		} else if (jdkLevel >= ClassFileConstants.getComplianceLevelForJavaVersion(ClassFileConstants.MAJOR_VERSION_16)) {
 			JLSLevel = AST_INTERNAL_JLS16;
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/RunConverterTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/RunConverterTests.java
index 48155f8..918141d 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/RunConverterTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/RunConverterTests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2021 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -35,6 +35,7 @@
 		ASTConverterBugsTestJLS3.class,
 		ASTConverterJavadocTest.class,
 		ASTConverterJavadocTest_15.class,
+		ASTConverterJavadocTest_18.class,
 		ASTConverter15Test.class,
 		ASTConverter16Test.class,
 		ASTConverter17Test.class,
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java
index 312df52..6d9c981 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2021 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -7525,8 +7525,8 @@
 		"	 *            a <code>String</coe> value that will be the text of\n" +
 		"	\n" +
 		"	* the paragraph.\n" +
-		"	 * &#64;return a <code>Paragraph</code> containing the the text passed as\n" +
-		"	 *            the reportHeader parameter.\n" +
+		"	 * @return a <code>Paragraph</code> containing the the text passed as the\n" +
+		"	 *            reportHeader parameter.\n" +
 		"	 */\n" +
 		"\n" +
 		"	public static String createReportHeader(String reportHeader) {\n" +
@@ -12800,17 +12800,7 @@
 		" */\n" +
 		"class Test {\n" +
 		"}";
-	formatSource(source,
-		"/**\n" +
-		" * <code>a<code>\n" +
-		" *\n" +
-		" * &#64;param   b\n" +
-		" *               c\n" +
-		" *            d</code>\n" +
-		" */\n" +
-		"class Test {\n" +
-		"}"
-	);
+	formatSource(source);
 }
 /**
  * https://bugs.eclipse.org/373625 - [formatter] preserve whitespace between
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterCommentsBugsTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterCommentsBugsTest.java
index 1c71a4e..ca478bf 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterCommentsBugsTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterCommentsBugsTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2019 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -3433,7 +3433,7 @@
 		"/**\n" +
 		" * <pre>\n" +
 		" * public class Test implements Runnable {\n" +
-		" * 	&#64;Override\n" +
+		" * 	@Override\n" +
 		" * 	public void run() {\n" +
 		" * 		// Hello really bad Ganymede formatter !!!\n" +
 		" * 		// Shit happens when somebody tries to change a running system\n" +
@@ -5167,14 +5167,11 @@
 		"	 * {@code public\n" +
 		"	 * static final} bimaps (\"constant bimaps\"). Example:\n" +
 		"	 * \n" +
-		"	 * <pre>\n" +
-		"	 * {\n" +
-		"	 * 	&#64;code\n" +
+		"	 * <pre>   {@code\n" +
 		"	 *\n" +
-		"	 * 	static final ImmutableBiMap<String, Integer> WORD_TO_INT = new ImmutableBiMap.Builder<String, Integer>()\n" +
-		"	 * 			.put(\"one\", 1).put(\"two\", 2).put(\"three\", 3).build();\n" +
-		"	 * }\n" +
-		"	 * </pre>\n" +
+		"	 * static final ImmutableBiMap<String, Integer> WORD_TO_INT = new ImmutableBiMap.Builder<String, Integer>()\n" +
+		"	 * 		.put(\"one\", 1).put(\"two\", 2).put(\"three\", 3).build();\n" +
+		"	 * }</pre>\n" +
 		"	 *\n" +
 		"	 * For <i>small</i> immutable bimaps, the {@code ImmutableBiMap.of()}\n" +
 		"	 * methods are even more convenient.\n" +
@@ -6253,18 +6250,15 @@
 	formatSource(source,
 		"public class X {\n" +
 		"	/**\n" +
-		"	 * <pre>\n" +
-		"	 * {\n" +
-		"	 * 	&#64;code\n" +
+		"	 * <pre>   {@code\n" +
 		"	 * \n" +
-		"	 * 	public class X {\n" +
-		"	 * 	}\n" +
+		"	 * public class X {\n" +
 		"	 * }\n" +
-		"	 * </pre>\n" +
+		"	 * }</pre>\n" +
 		"	 */\n" +
 		"	public void foo() {\n" +
 		"	}\n" +
-	    "}\n");
+		"}\n");
 }
 public void testBug300379b() {
 	String source =
@@ -6280,18 +6274,15 @@
 	formatSource(source,
 		"public class X {\n" +
 		"	/**\n" +
-		"	 * <pre>\n" +
-		"	 * {\n" +
-		"	 * 	&#64;code\n" +
+		"	 * <pre>   {@code\n" +
 		"	 * \n" +
-		"	 * 	public class X {\n" +
-		"	 * 	}\n" +
+		"	 * public class X {\n" +
 		"	 * }\n" +
-		"	 * </pre>\n" +
+		"	 * }</pre>\n" +
 		"	 */\n" +
 		"	public void foo() {\n" +
 		"	}\n" +
-	    "}\n");
+		"}\n");
 }
 
 /**
@@ -7672,4 +7663,115 @@
 		"}";
 	formatSource(source);
 }
+/**
+ * https://bugs.eclipse.org/552012 - Javadoc formatting breaks {@code} code block.
+ */
+public void testBug552012a() {
+	setComplianceLevel(CompilerOptions.VERSION_17);
+	String source =
+		"/**\n" +
+		" * Test1\n" +
+		" * <pre>{@code\n" +
+		" * public class X {@Deprecated int    a    ;\n" +
+		" * }\n" +
+		" * }</pre>\n" +
+		" * Test2\n" +
+		" * <pre>{@code int    a = 1   ;}</pre>\n" +
+		" * Test3\n" +
+		" * <pre>\n" +
+		" * code sample: {@code public   void foo( ){}  }\n" +
+		" * literal sample: {@literal public   void foo( ){}  }\n" +
+		" * the end\n" +
+		" * </pre>\n" +
+		" */\n" +
+		"public class MyTest {\n" +
+		"}";
+	formatSource(source,
+		"/**\n" +
+		" * Test1\n" +
+		" * \n" +
+		" * <pre>{@code\n" +
+		" * public class X {\n" +
+		" * 	@Deprecated\n" +
+		" * 	int a;\n" +
+		" * }\n" +
+		" * }</pre>\n" +
+		" * \n" +
+		" * Test2\n" +
+		" * \n" +
+		" * <pre>{@code\n" +
+		" * int a = 1;\n" +
+		" * }</pre>\n" +
+		" * \n" +
+		" * Test3\n" +
+		" * \n" +
+		" * <pre>\n" +
+		" * code sample: {@code\n" +
+		" * public void foo() {\n" +
+		" * }\n" +
+		" * }\n" +
+		" * literal sample: {@literal public   void foo( ){}  }\n" +
+		" * the end\n" +
+		" * </pre>\n" +
+		" */\n" +
+		"public class MyTest {\n" +
+		"}");
+}
+/**
+ * https://bugs.eclipse.org/552012 - Javadoc formatting breaks {@code} code block.
+ */
+public void testBug552012b() {
+	String source =
+		"/**\n" +
+		" * <pre>{@code\n" +
+		" * public class X {@Deprecated int    a    ;\n" +
+		" * }\n" +
+		" * }</pre>\n" +
+		" */\n" +
+		"public class MyTest {\n" +
+		"}";
+	formatSource(source,
+		"/**\n" +
+		" * <pre>{@code\n" +
+		" * public class X { @Deprecated\n" +
+		" * 	int a;\n" +
+		" * }\n" +
+		" * }</pre>\n" +
+		" */\n" +
+		"public class MyTest {\n" +
+		"}");
+}
+/**
+ * https://bugs.eclipse.org/552012 - Javadoc formatting breaks {@code} code block.
+ */
+public void testBug552012c() {
+	String source =
+		"/**\n" +
+		" * <pre>@something something</pre>\n" +
+		" */\n" +
+		"public class MyTest {\n" +
+		"}";
+	formatSource(source,
+		"/**\n" +
+		" * <pre>\n" +
+		" * &#64;something something\n" +
+		" * </pre>\n" +
+		" */\n" +
+		"public class MyTest {\n" +
+		"}");
+}
+/**
+ * https://bugs.eclipse.org/552012 - Javadoc formatting breaks {@code} code block.
+ */
+public void testBug552012d() {
+	String source =
+		"/**\n" +
+		" * <pre>\n" +
+		" * @something something\n" +
+		" * </pre>\n" +
+		" */\n" +
+		"public class MyTest {\n" +
+		"}";
+	formatSource(source);
+}
 }
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java
index a44f5d3..f805d3c 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java
@@ -15948,7 +15948,7 @@
  * https://bugs.eclipse.org/573949 - [17][switch pattern][formatter] JEP 406 changes
  */
 public void testBug573949() {
-	setComplianceLevel(CompilerOptions.VERSION_17);
+	setComplianceLevel(CompilerOptions.VERSION_18);
 	String source =
 		"public class X {\n" +
 		" private static void foo(Object o) {\n" +
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java
index 40b9217..38c524d 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2021 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -7,6 +7,7 @@
  * https://www.eclipse.org/legal/epl-2.0/
  *
  * SPDX-License-Identifier: EPL-2.0
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -27,6 +28,7 @@
 import java.util.Map;
 import java.util.stream.Collectors;
 
+import org.eclipse.core.internal.resources.CharsetDeltaJob;
 import org.eclipse.core.resources.IContainer;
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IFolder;
@@ -158,6 +160,7 @@
 	protected static boolean isJRE15 = false;
 	protected static boolean isJRE16 = false;
 	protected static boolean isJRE17 = false;
+	protected static boolean isJRE18 = false;
 	static {
 		String javaVersion = System.getProperty("java.version");
 		String vmName = System.getProperty("java.vm.name");
@@ -170,6 +173,9 @@
 			}
 		}
 		long jdkLevel = CompilerOptions.versionToJdkLevel(javaVersion.length() > 3 ? javaVersion.substring(0, 3) : javaVersion);
+		if (jdkLevel >= ClassFileConstants.JDK18) {
+			isJRE18 = true;
+		}
 		if (jdkLevel >= ClassFileConstants.JDK17) {
 			isJRE17 = true;
 		}
@@ -254,9 +260,13 @@
 
 	/**
 	 * Internal synonym for constant AST.JSL17
+	 * @deprecated
 	 */
 	protected static final int AST_INTERNAL_JLS17 = AST.JLS17;
-
+	/**
+	 * Internal synonym for constant AST.JSL18
+	 */
+	protected static final int AST_INTERNAL_JLS18 = AST.JLS18;
 	/**
 	 * Internal synonym for the latest AST level.
 	 *
@@ -1610,7 +1620,9 @@
 				if (parent instanceof IFolder && !parent.exists()) {
 					createFolder(parent.getFullPath());
 				}
-				folder.create(true, true, null);
+				if(!folder.exists()) {
+					folder.create(true, true, null);
+				}
 			}
 		},
 		null);
@@ -3382,9 +3394,11 @@
 			public void run(IProgressMonitor monitor) throws CoreException {
 				project.create(null);
 				project.open(null);
+				project.setDefaultCharset(ResourcesPlugin.getEncoding(), monitor);
 			}
 		};
 		getWorkspace().run(populate, null);
+		waitForCharsetDeltaJob();
 		IJavaProject javaProject = JavaCore.create(project);
 		setUpProjectCompliance(javaProject, compliance, useFullJCL);
 		javaProject.setOption(JavaCore.COMPILER_PB_UNUSED_LOCAL, JavaCore.IGNORE);
@@ -3840,6 +3854,14 @@
 		return new Path(System.getProperty("java.home") + "/lib/jrt-fs.jar");
 	}
 
+	public void waitForCharsetDeltaJob() throws CoreException {
+		try {
+			Job.getJobManager().join(CharsetDeltaJob.FAMILY_CHARSET_DELTA, null);
+		} catch (OperationCanceledException | InterruptedException e) {
+			throw new CoreException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, e.getMessage(), e));
+		}
+	}
+
 	/**
 	 * Wait for autobuild notification to occur
 	 */
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests17.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests17.java
index a6aaafb..76be47e 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests17.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests17.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2021 IBM Corporation and others.
+ * Copyright (c) 2021, 2022 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
@@ -127,7 +127,7 @@
 		this.workingCopies[0] = getWorkingCopy(
 				"/Completion/src/X.java",
 				"public class X {\n" +
-						"public static  int field \n" +
+						"public static  int field; \n" +
 						"public static void main(String[] args) {\n" +
 						"foo(Integer.valueOf(5));\n" +
 						"foo(new Object());\n" +
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests18.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests18.java
index b8b9d4e..d1d56c5 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests18.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests18.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2014, 2020 IBM Corporation and others.
+ * Copyright (c) 2014, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -6463,4 +6463,40 @@
 			+ "ArrayList<java.lang.String>[TYPE_REF]{ArrayList, java.util, Ljava.util.ArrayList<Ljava.lang.String;>;, null, null, 82}",
 			result);
 }
+public void testBug578817() throws JavaModelException {
+	this.workingCopies = new ICompilationUnit[1];
+	this.workingCopies[0] = getWorkingCopy(
+			"Completion/src/Bug578817.java",
+			"import java.util.Map;\n" +
+			"\n" +
+			"public class Bug578817 {\n" +
+			"	private void foo() {\n" +
+			"		Map map = new LinkedHashMap\n"+
+			"	}\n" +
+			"}\n");
+
+	CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true);
+	requestor.setAllowsRequiredProposals(CompletionProposal.TYPE_REF, CompletionProposal.TYPE_REF, true);
+	requestor.setAllowsRequiredProposals(CompletionProposal.CONSTRUCTOR_INVOCATION, CompletionProposal.TYPE_REF, true);
+	String str = this.workingCopies[0].getSource();
+	String completeBehind = "new LinkedHashMap";
+	int cursorLocation = str.indexOf(completeBehind) + completeBehind.length();
+	this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner, new NullProgressMonitor());
+	String result = requestor.getResults();
+	assertResults("LinkedHashMap[CONSTRUCTOR_INVOCATION]{(), Ljava.util.LinkedHashMap;, ()V, LinkedHashMap, null, 76}\n"
+			+ "LinkedHashMap[CONSTRUCTOR_INVOCATION]{(), Ljava.util.LinkedHashMap;, (I)V, LinkedHashMap, (arg0), 76}\n"
+			+ "LinkedHashMap[CONSTRUCTOR_INVOCATION]{(), Ljava.util.LinkedHashMap;, (IF)V, LinkedHashMap, (arg0, arg1), 76}\n"
+			+ "LinkedHashMap[CONSTRUCTOR_INVOCATION]{(), Ljava.util.LinkedHashMap;, (IFZ)V, LinkedHashMap, (arg0, arg1, arg2), 76}\n"
+			+ "LinkedHashMap[CONSTRUCTOR_INVOCATION]{(), Ljava.util.LinkedHashMap;, (Ljava.util.Map<+TK;+TV;>;)V, LinkedHashMap, (arg0), 76}", result);
+
+	requestor = new CompletionTestsRequestor2(true);
+	requestor.setAllowsRequiredProposals(CompletionProposal.TYPE_REF, CompletionProposal.TYPE_REF, true);
+	requestor.setAllowsRequiredProposals(CompletionProposal.CONSTRUCTOR_INVOCATION, CompletionProposal.TYPE_REF, true);
+	requestor.setTypeProposalFilter((typeName) -> {
+		return typeName.startsWith("java.util.");
+	});
+	this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner, new NullProgressMonitor());
+	result = requestor.getResults();
+	assertResults("", result);
+}
 }
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTestsRequestor2.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTestsRequestor2.java
index 48a203c..a97f7e8 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTestsRequestor2.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTestsRequestor2.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2020 IBM Corporation and others.
+ * Copyright (c) 2004, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -56,6 +56,7 @@
 	public boolean debug = false;
 
 	private Predicate<CompletionProposal> proposalFilter = x -> true;
+	private Predicate<String> typeProposalFilter = x -> false;
 
 	public CompletionTestsRequestor2() {
 		this(false, false);
@@ -111,6 +112,15 @@
 		this.proposals[this.proposalsPtr] = proposal;
 	}
 
+	@Override
+	public boolean isIgnored(char[] typeName) {
+		if (this.typeProposalFilter != null) {
+			return this.typeProposalFilter.test(new String(typeName));
+		}
+
+		return super.isIgnored(typeName);
+	}
+
 	public void allowAllRequiredProposals() {
 		for (int i = CompletionProposal.ANONYMOUS_CLASS_DECLARATION; i <= CompletionProposal.ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION; i++) {
 			for (int j = CompletionProposal.ANONYMOUS_CLASS_DECLARATION; j <= CompletionProposal.ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION; j++) {
@@ -656,6 +666,9 @@
 		this.proposalFilter = proposalFilter;
 	}
 
+	public void setTypeProposalFilter(Predicate<String> typeProposalFilter) {
+		this.typeProposalFilter = typeProposalFilter;
+	}
 	public boolean canUseDiamond(int proposalNo) {
 		if (proposalNo < this.proposals.length && this.proposals[proposalNo] != null) {
 			return this.proposals[proposalNo].canUseDiamond(this.context);
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExclusionPatternsTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExclusionPatternsTests.java
index 0222e0d..efd4f84 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExclusionPatternsTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExclusionPatternsTests.java
@@ -122,6 +122,7 @@
 			"Unexpected non-java resources of project",
 			".classpath\n" +
 			".project\n" +
+			".settings\n" +
 			"doc",
 			javaProject.getNonJavaResources());
 	} finally {
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java
index 8ccdb46..be6e238 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java
@@ -170,7 +170,7 @@
 		super.setUpSuite();
 
 		Bundle[] bundles = getAnnotationBundles();
-		File bundleFile = FileLocator.getBundleFile(bundles[0]);
+		File bundleFile = FileLocator.getBundleFileLocation(bundles[0]).get();
 		this.ANNOTATION_LIB = bundleFile.isDirectory() ? bundleFile.getPath()+"/bin" : bundleFile.getPath();
 
 		// set up class path container bridging to the host JRE:
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/InclusionPatternsTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/InclusionPatternsTests.java
index 19c2b40..24a85ee 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/InclusionPatternsTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/InclusionPatternsTests.java
@@ -114,7 +114,8 @@
 		assertResourceNamesEqual(
 			"Unexpected non-java resources of project",
 			".classpath\n" +
-			".project",
+			".project\n" +
+			".settings",
 			javaProject.getNonJavaResources());
 	} finally {
 		deleteProject("P1");
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaElementDeltaTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaElementDeltaTests.java
index c7a4277..a25c841 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaElementDeltaTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaElementDeltaTests.java
@@ -1982,10 +1982,10 @@
 		final IProject projectFolder = project.getProject();
 		final IFolder folder = createFolder("/P/folder");
 
-		startDeltas();
 		getWorkspace().run(
 			new IWorkspaceRunnable() {
 				public void run(IProgressMonitor monitor) throws CoreException {
+					startDeltas();
 					IProjectDescription desc = projectFolder.getDescription();
 					desc.setComment("A comment");
 					projectFolder.setDescription(desc, null);
@@ -2359,7 +2359,8 @@
 			"	<project root>[*]: {ADDED TO CLASSPATH}\n" +
 			"	lib.jar[-]: {}\n" +
 			"	ResourceDelta(/P/.classpath)[*]\n" +
-			"	ResourceDelta(/P/.project)[*]"
+			"	ResourceDelta(/P/.project)[*]\n" +
+			"	ResourceDelta(/P/.settings)[*]"
 		);
 	} finally {
 		stopDeltas();
@@ -2387,7 +2388,8 @@
 			"\n" +
 			"P[*]: {CONTENT}\n" +
 			"	ResourceDelta(/P/.classpath)[*]\n" +
-			"	ResourceDelta(/P/.project)[*]"
+			"	ResourceDelta(/P/.project)[*]\n" +
+			"	ResourceDelta(/P/.settings)[*]"
 		);
 	} finally {
 		stopDeltas();
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java
index ff4f252..8b4fcd8 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java
@@ -1089,7 +1089,8 @@
 		assertResourcesEqual(
 			"Unexpected non-java resources for project",
 			"/P/.classpath\n" +
-			"/P/.project",
+			"/P/.project\n" +
+			"/P/.settings",
 			project.getNonJavaResources());
 	} finally {
 		this.deleteProject("P");
@@ -1105,7 +1106,8 @@
 		assertResourcesEqual(
 			"Unexpected non-java resources for project",
 			"/P/.classpath\n" +
-			"/P/.project",
+			"/P/.project\n" +
+			"/P/.settings",
 			project.getNonJavaResources());
 	} finally {
 		this.deleteProject("P");
@@ -1121,7 +1123,8 @@
 		assertResourcesEqual(
 			"Unexpected non-java resources for project",
 			"/P/.classpath\n" +
-			"/P/.project",
+			"/P/.project\n" +
+			"/P/.settings",
 			project.getNonJavaResources());
 	} finally {
 		this.deleteProject("P");
@@ -1139,6 +1142,7 @@
 			"Unexpected non-java resources for project",
 			"/P/.classpath\n" +
 			"/P/.project\n" +
+			"/P/.settings\n" +
 			"/P/x.y",
 			project.getNonJavaResources());
 	} finally {
@@ -1156,7 +1160,8 @@
 		assertResourcesEqual(
 			"Unexpected non-java resources for project",
 			"/P/.classpath\n" +
-			"/P/.project",
+			"/P/.project\n" +
+			"/P/.settings",
 			project.getNonJavaResources());
 	} finally {
 		this.deleteProject("P");
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/NullAnnotationModelTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/NullAnnotationModelTests.java
index 68ff77f..559a4ce 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/NullAnnotationModelTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/NullAnnotationModelTests.java
@@ -76,7 +76,7 @@
 	}
 
 	static {
-		TESTS_NAMES = new String[] { "testTargetTypeUse" };
+//		TESTS_NAMES = new String[] { "testBug565246" };
 	}
 
 	/**
@@ -86,11 +86,11 @@
 	public void setUp() throws Exception {
 		super.setUp();
 		Bundle[] bundles = org.eclipse.jdt.core.tests.Activator.getPackageAdmin().getBundles("org.eclipse.jdt.annotation", "[2.0.0,3.0.0)");
-		File bundleFile = FileLocator.getBundleFile(bundles[0]);
+		File bundleFile = FileLocator.getBundleFileLocation(bundles[0]).get();
 		this.ANNOTATION_LIB = bundleFile.isDirectory() ? bundleFile.getPath()+"/bin" : bundleFile.getPath();
 
 		bundles = org.eclipse.jdt.core.tests.Activator.getPackageAdmin().getBundles("org.eclipse.jdt.annotation", "[1.1.0,2.0.0)");
-		bundleFile = FileLocator.getBundleFile(bundles[0]);
+		bundleFile = FileLocator.getBundleFileLocation(bundles[0]).get();
 		this.ANNOTATION_LIB_V1 = bundleFile.isDirectory() ? bundleFile.getPath()+"/bin" : bundleFile.getPath();
 	}
 
@@ -1147,4 +1147,43 @@
 			deleteProject(project);
 		}
 	}
+	public void testBug565246() throws CoreException {
+		IJavaProject project = createJavaProject("Bug565246", new String[] {"src"}, new String[] {"JCL17_LIB", this.ANNOTATION_LIB_V1}, "bin", "1.7");
+		try {
+			project.setOption(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
+			createFolder("Bug565246/src/java/util");
+			createFile("Bug565246/src/java/util/Iterator.java",
+					"package java.util;\n" +
+					"import org.eclipse.jdt.annotation.NonNullByDefault;\n" +
+					"\n" +
+					"@NonNullByDefault\n" +
+					"public interface Iterator<E> {\n" +
+					"	boolean hasNext();\n" +
+					"\n" +
+					"	E next();\n" +
+					"}\n");
+			getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+
+			String testSourcePath = "Bug565246/src/Test.java";
+			createFile(testSourcePath,
+					"import org.eclipse.jdt.annotation.NonNull;\n" +
+					"import java.util.Collection;\n" +
+					"public class Test {\n" +
+					"	public void foo(Collection<String> list) {\n" +
+					"		for (String s : list)\n" +
+					"			bar(s);\n" +
+					"	}\n" +
+					"	void bar(@NonNull String s) {}\n" +
+					"}\n");
+
+			getCompilationUnit(testSourcePath).getWorkingCopy(this.wcOwner, null);
+			assertProblems("", "----------\n----------\n");
+
+			getWorkspace().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, null);
+			IMarker[] markers = project.getProject().findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers", "", markers);
+		} finally {
+			deleteProject(project);
+		}
+	}
 }
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ReconcilerTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ReconcilerTests.java
index 71c53fb..1cdad34 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ReconcilerTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ReconcilerTests.java
@@ -5873,7 +5873,7 @@
 		deleteProjects(new String[] { "P" });
 	}
 }
-public void testBug485092() throws CoreException, IOException, InterruptedException {
+public void testBug485092() throws CoreException, InterruptedException {
 
 	IJavaProject project15 = null;
 	IJavaProject project18 = null;
@@ -5918,7 +5918,7 @@
 
 		project18.setOption(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
 		Bundle[] bundles = Platform.getBundles("org.eclipse.jdt.annotation","[2.0.0,3.0.0)");
-		File bundleFile = FileLocator.getBundleFile(bundles[0]);
+		File bundleFile = FileLocator.getBundleFileLocation(bundles[0]).get();
 		String annotationsLib = bundleFile.isDirectory() ? bundleFile.getPath()+"/bin" : bundleFile.getPath();
 		IClasspathEntry nullAnnotationsClassPathEntry = JavaCore.newLibraryEntry(new Path(annotationsLib), null, null);
 
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/RootManipulationsTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/RootManipulationsTests.java
index 2ff19ad..f401d19 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/RootManipulationsTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/RootManipulationsTests.java
@@ -344,7 +344,8 @@
 			"		p\n" +
 			"			X.java\n" +
 			"	L/P2/.classpath\n" +
-			"	L/P2/.project",
+			"	L/P2/.project\n" +
+			"	F/P2/.settings",
 			p2);
 	} finally {
 		stopDeltas();
@@ -393,7 +394,8 @@
 			"		p\n" +
 			"			X.java\n" +
 			"	L/P/.classpath\n" +
-			"	L/P/.project",
+			"	L/P/.project\n" +
+			"	F/P/.settings",
 			project);
 	} finally {
 		stopDeltas();
@@ -470,7 +472,8 @@
 			"	src\n" +
 			"		<default>\n" +
 			"	L/P/.classpath\n" +
-			"	L/P/.project",
+			"	L/P/.project\n" +
+			"	F/P/.settings",
 			project);
 	} finally {
 		stopDeltas();
@@ -500,7 +503,8 @@
 			"	src\n" +
 			"		<default>\n" +
 			"	L/P/.classpath\n" +
-			"	L/P/.project",
+			"	L/P/.project\n" +
+			"	F/P/.settings",
 			project);
 	} finally {
 		stopDeltas();
@@ -534,14 +538,16 @@
 			"	src\n" +
 			"		<default>\n" +
 			"	L/P1/.classpath\n" +
-			"	L/P1/.project",
+			"	L/P1/.project\n" +
+			"	F/P1/.settings",
 			p1);
 		assertJavaProject(
 			"P2\n" +
 			"	src\n" +
 			"		<default>\n" +
 			"	L/P2/.classpath\n" +
-			"	L/P2/.project",
+			"	L/P2/.project\n" +
+			"	F/P2/.settings",
 			p2);
 	} finally {
 		stopDeltas();
@@ -575,7 +581,8 @@
 		assertJavaProject(
 			"P\n" +
 			"	L/P/.classpath\n" +
-			"	L/P/.project",
+			"	L/P/.project\n" +
+			"	F/P/.settings",
 			project);
 	} finally {
 		stopDeltas();
@@ -625,6 +632,7 @@
 			"			Y.java\n" +
 			"	L/P/.classpath\n" +
 			"	L/P/.project\n" +
+			"	F/P/.settings\n" +
 			"	F/P/src1",
 			project);
 
@@ -665,7 +673,8 @@
 		assertJavaProject(
 			"P1\n" +
 			"	L/P1/.classpath\n" +
-			"	L/P1/.project",
+			"	L/P1/.project\n" +
+			"	F/P1/.settings",
 			p1);
 		assertJavaProject(
 			"P2\n" +
@@ -674,7 +683,8 @@
 			"		p\n" +
 			"			X.java\n" +
 			"	L/P2/.classpath\n" +
-			"	L/P2/.project",
+			"	L/P2/.project\n" +
+			"	F/P2/.settings",
 			p2);
 	} finally {
 		stopDeltas();
@@ -714,7 +724,8 @@
 		assertJavaProject(
 			"P1\n" +
 			"	L/P1/.classpath\n" +
-			"	L/P1/.project",
+			"	L/P1/.project\n" +
+			"	F/P1/.settings",
 			p1);
 		assertJavaProject(
 			"P2\n" +
@@ -723,7 +734,8 @@
 			"		p\n" +
 			"			X.java\n" +
 			"	L/P2/.classpath\n" +
-			"	L/P2/.project",
+			"	L/P2/.project\n" +
+			"	F/P2/.settings",
 			p2);
 	} finally {
 		stopDeltas();
@@ -778,6 +790,7 @@
 			"			Y.java\n" +
 			"	L/P1/.classpath\n" +
 			"	L/P1/.project\n" +
+			"	F/P1/.settings\n" +
 			"	F/P1/src1",
 			p1);
 		assertJavaProject(
@@ -787,7 +800,8 @@
 			"		p\n" +
 			"			X.java\n" +
 			"	L/P2/.classpath\n" +
-			"	L/P2/.project",
+			"	L/P2/.project\n" +
+			"	F/P2/.settings",
 			p2);
 	} finally {
 		stopDeltas();
@@ -823,7 +837,8 @@
 		assertJavaProject(
 			"P1\n" +
 			"	L/P1/.classpath\n" +
-			"	L/P1/.project",
+			"	L/P1/.project\n" +
+			"	F/P1/.settings",
 			p1);
 		assertJavaProject(
 			"P2\n" +
@@ -834,7 +849,8 @@
 			"	src2\n" +
 			"		<default>\n" +
 			"	L/P2/.classpath\n" +
-			"	L/P2/.project",
+			"	L/P2/.project\n" +
+			"	F/P2/.settings",
 			p2);
 	} finally {
 		stopDeltas();
@@ -869,7 +885,8 @@
 		assertJavaProject(
 			"P1\n" +
 			"	L/P1/.classpath\n" +
-			"	L/P1/.project",
+			"	L/P1/.project\n" +
+			"	F/P1/.settings",
 			p1);
 		assertJavaProject(
 			"P2\n" +
@@ -880,7 +897,8 @@
 			"	src2\n" +
 			"		<default>\n" +
 			"	L/P2/.classpath\n" +
-			"	L/P2/.project",
+			"	L/P2/.project\n" +
+			"	F/P2/.settings",
 			p2);
 	} finally {
 		stopDeltas();
@@ -913,7 +931,8 @@
 		assertJavaProject(
 			"P1\n" +
 			"	L/P1/.classpath\n" +
-			"	L/P1/.project",
+			"	L/P1/.project\n" +
+			"	F/P1/.settings",
 			p1);
 		assertJavaProject(
 			"P2\n" +
@@ -924,7 +943,8 @@
 			"	src\n" +
 			"		<default>\n" +
 			"	L/P2/.classpath\n" +
-			"	L/P2/.project",
+			"	L/P2/.project\n" +
+			"	F/P2/.settings",
 			p2);
 	} finally {
 		stopDeltas();
@@ -963,7 +983,8 @@
 			"		p\n" +
 			"			X.java\n" +
 			"	L/P/.classpath\n" +
-			"	L/P/.project",
+			"	L/P/.project\n" +
+			"	F/P/.settings",
 			project);
 	} finally {
 		stopDeltas();
@@ -1061,7 +1082,8 @@
 			"	src3\n" +
 			"		<default>\n" +
 			"	L/P/.classpath\n" +
-			"	L/P/.project",
+			"	L/P/.project\n" +
+			"	F/P/.settings",
 			project);
 
 		// rename src2
@@ -1084,7 +1106,8 @@
 			"	src3\n" +
 			"		<default>\n" +
 			"	L/P/.classpath\n" +
-			"	L/P/.project",
+			"	L/P/.project\n" +
+			"	F/P/.settings",
 			project);
 
 		// rename src3
@@ -1107,7 +1130,8 @@
 			"	src6\n" +
 			"		<default>\n" +
 			"	L/P/.classpath\n" +
-			"	L/P/.project",
+			"	L/P/.project\n" +
+			"	F/P/.settings",
 			project);
 	} finally {
 		stopDeltas();
@@ -1139,7 +1163,8 @@
 			"		<default>\n" +
 			"	myLib2.jar\n" +
 			"	L/P/.classpath\n" +
-			"	L/P/.project",
+			"	L/P/.project\n" +
+			"	F/P/.settings",
 			project);
 	} finally {
 		stopDeltas();
@@ -1176,7 +1201,8 @@
 			"		<default>\n" +
 			"	myLib2.jar\n" +
 			"	L/P1/.classpath\n" +
-			"	L/P1/.project",
+			"	L/P1/.project\n" +
+			"	F/P1/.settings",
 			p1);
 		assertJavaProject(
 			"P2\n" +
@@ -1184,7 +1210,8 @@
 			"		<default>\n" +
 			"	/P1/myLib2.jar\n" +
 			"	L/P2/.classpath\n" +
-			"	L/P2/.project",
+			"	L/P2/.project\n" +
+			"	F/P2/.settings",
 			p2);
 	} finally {
 		stopDeltas();
@@ -1225,7 +1252,8 @@
 			"		<default>\n" +
 			"	myLib2.jar\n" +
 			"	L/P/.classpath\n" +
-			"	L/P/.project",
+			"	L/P/.project\n" +
+			"	F/P/.settings",
 			project);
 	} finally {
 		stopDeltas();
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingRecordDeclarationTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingRecordDeclarationTest.java
index d1b8343..adb2c48 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingRecordDeclarationTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingRecordDeclarationTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (c) 2020, 2021 IBM Corporation and others.
+* Copyright (c) 2020, 2022 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
@@ -63,7 +63,6 @@
 	protected void setUp() throws Exception {
 		super.setUp();
 		setUpProjectAbove16();
-		setUpProjectAbove17();
 	}
 
 	@SuppressWarnings("deprecation")
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingSwitchExpressionsTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingSwitchExpressionsTest.java
index 0238c26..f135fce 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingSwitchExpressionsTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingSwitchExpressionsTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2019, 2021 IBM Corporation and others.
+ * Copyright (c) 2019, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -7,6 +7,7 @@
  * https://www.eclipse.org/legal/epl-2.0/
  *
  * SPDX-License-Identifier: EPL-2.0
+ *
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
 package org.eclipse.jdt.core.tests.rewrite.describing;
@@ -53,7 +54,6 @@
 	protected void setUp() throws Exception {
 		super.setUp();
 		super.setUpProjectAbove14();
-		setUpProjectAbove17();
 
 	}
 
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingSwitchPatternTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingSwitchPatternTest.java
index c61b680..69789a4 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingSwitchPatternTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingSwitchPatternTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2021 IBM Corporation and others.
+ * Copyright (c) 2021, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -53,23 +53,23 @@
 	}
 
 	public static Test suite() {
-		return createSuite(ASTRewritingSwitchPatternTest.class, 17);
+		return createSuite(ASTRewritingSwitchPatternTest.class, 18);
 	}
 
 	@Override
 	protected void setUp() throws Exception {
 		super.setUp();
-		if (this.apiLevel == AST.JLS17 ) { // Remove this after it is a standard feature
-			this.project1.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_17);
-			this.project1.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_17);
-			this.project1.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_17);
+		if (this.apiLevel == AST.JLS18 ) { // Remove this after it is a standard feature
+			this.project1.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_18);
+			this.project1.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_18);
+			this.project1.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_18);
 			this.project1.setOption(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES, JavaCore.ENABLED);
 		}
 	}
 
 	private boolean checkAPILevel() {
-		if (this.apiLevel < 17) {
-			System.err.println("Test "+getName()+" requires a JRE 17");
+		if (this.apiLevel < 18) {
+			System.err.println("Test "+getName()+" requires a JRE 18");
 			return true;
 		}
 		return false;
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingTest.java
index 8e2b199..0ce6f37 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2021 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -7,6 +7,7 @@
  * https://www.eclipse.org/legal/epl-2.0/
  *
  * SPDX-License-Identifier: EPL-2.0
+ *
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
 package org.eclipse.jdt.core.tests.rewrite.describing;
@@ -91,9 +92,12 @@
 	/** @deprecated using deprecated code */
 	private final static int JLS16_INTERNAL = AST.JLS16;
 
+	/** @deprecated using deprecated code */
 	private final static int JLS17_INTERNAL = AST.JLS17;
 
-	private final static int[] JLS_LEVELS = { JLS2_INTERNAL, JLS3_INTERNAL, JLS4_INTERNAL, JLS8_INTERNAL, JLS9_INTERNAL, JLS10_INTERNAL, JLS14_INTERNAL, JLS15_INTERNAL, JLS16_INTERNAL, JLS17_INTERNAL};
+	private final static int JLS18_INTERNAL = AST.JLS18;
+
+	private final static int[] JLS_LEVELS = { JLS2_INTERNAL, JLS3_INTERNAL, JLS4_INTERNAL, JLS8_INTERNAL, JLS9_INTERNAL, JLS10_INTERNAL, JLS14_INTERNAL, JLS15_INTERNAL, JLS16_INTERNAL, JLS17_INTERNAL, JLS18_INTERNAL};
 
 	private static final String ONLY_AST_STRING = "_only";
 	private static final String SINCE_AST_STRING = "_since";
@@ -255,14 +259,25 @@
 			this.project1.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_16);
 			this.project1.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_16);
 		}
+		setUpProjectAbove17();
 	}
 
+	@SuppressWarnings("deprecation")
 	protected void setUpProjectAbove17() throws Exception {
 		if (this.apiLevel == AST_INTERNAL_JLS17 ) {
 			this.project1.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_17);
 			this.project1.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_17);
 			this.project1.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_17);
 		}
+		setUpProjectAbove18();
+	}
+
+	protected void setUpProjectAbove18() throws Exception {
+		if (this.apiLevel == AST_INTERNAL_JLS18 ) {
+			this.project1.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_18);
+			this.project1.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_18);
+			this.project1.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_18);
+		}
 	}
 
 	protected IJavaProject createProject(String projectName, String complianceVersion) throws CoreException {
diff --git a/org.eclipse.jdt.core/.settings/.api_filters b/org.eclipse.jdt.core/.settings/.api_filters
index 0b95b00..905fdaa 100644
--- a/org.eclipse.jdt.core/.settings/.api_filters
+++ b/org.eclipse.jdt.core/.settings/.api_filters
@@ -9,6 +9,29 @@
             </message_arguments>
         </filter>
     </resource>
+    <resource path="dom/org/eclipse/jdt/core/dom/AST.java" type="org.eclipse.jdt.core.dom.AST">
+        <filter comment="For new java version" id="388194388">
+            <message_arguments>
+                <message_argument value="org.eclipse.jdt.core.dom.AST"/>
+                <message_argument value="JLS_Latest"/>
+                <message_argument value="17"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="dom/org/eclipse/jdt/core/dom/AbstractTagElement.java" type="org.eclipse.jdt.core.dom.AbstractTagElement">
+        <filter id="576725006">
+            <message_arguments>
+                <message_argument value="IDocElement"/>
+                <message_argument value="TagProperty"/>
+            </message_arguments>
+        </filter>
+        <filter id="576778288">
+            <message_arguments>
+                <message_argument value="ASTNode"/>
+                <message_argument value="TagProperty"/>
+            </message_arguments>
+        </filter>
+    </resource>
     <resource path="dom/org/eclipse/jdt/core/dom/ASTNode.java" type="org.eclipse.jdt.core.dom.ASTNode">
         <filter comment="adjust constants after additions in JDT" id="388194388">
             <message_arguments>
diff --git a/org.eclipse.jdt.core/META-INF/MANIFEST.MF b/org.eclipse.jdt.core/META-INF/MANIFEST.MF
index d071ae8..7b46414 100644
--- a/org.eclipse.jdt.core/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.core/META-INF/MANIFEST.MF
@@ -1,7 +1,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.jdt.core; singleton:=true
-Bundle-Version: 3.29.0.OTDT_r282_qualifier
+Bundle-Version: 3.30.0.OTDT_r282_qualifier
 Bundle-Activator: org.eclipse.jdt.core.JavaCore
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
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 517a5c5..e9cad0a 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
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2021 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -3259,6 +3259,9 @@
 		case "17": //$NON-NLS-1$
 		case "17.0": //$NON-NLS-1$
 			return CompilerOptions.VERSION_17;
+		case "18": //$NON-NLS-1$
+		case "18.0": //$NON-NLS-1$
+			return CompilerOptions.VERSION_18;
 		default:
 			return null;
 	}
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
index 55ccec0..035f773 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
@@ -1,5 +1,5 @@
 ###############################################################################
-# Copyright (c) 2000, 2021 IBM Corporation and others.
+# Copyright (c) 2000, 2022 IBM Corporation and others.
 #
 # This program and the accompanying materials
 # are made available under the terms of the Eclipse Public License 2.0
@@ -72,7 +72,7 @@
 configure.unsupportedReleaseOption = option --release is supported only when run with JDK 9 or above
 configure.unsupportedWithRelease = option {0} is not supported when --release is used
 configure.unsupportedReleaseVersion = release version {0} is not supported
-configure.source = source level should be in ''1.1''...''1.8'',''9''...''17'' (or ''5.0''..''17.0''): {0}
+configure.source = source level should be in ''1.1''...''1.8'',''9''...''18'' (or ''5.0''..''18.0''): {0}
 configure.invalidSystem = invalid location for system libraries: {0}
 configure.unsupportedOption = option {0} not supported at compliance level 9 and above
 configure.duplicateOutputPath = duplicate output path specification: {0}
@@ -90,7 +90,7 @@
 configure.invalidWarningConfiguration = invalid warning configuration: ''{0}''
 configure.invalidWarning = invalid warning token: ''{0}''. Ignoring warning and compiling
 configure.invalidWarningOption = invalid warning option: ''{0}''. Must specify a warning token
-configure.targetJDK = target level should be in ''1.1''...''1.8'',''9''...''17'' (or ''5.0''..''17.0'') or cldc1.1: {0}
+configure.targetJDK = target level should be in ''1.1''...''1.8'',''9''...''18'' (or ''5.0''..''18.0'') or cldc1.1: {0}
 configure.incompatibleTargetForSource = Target level ''{0}'' is incompatible with source level ''{1}''. A target level ''{1}'' or better is required
 configure.incompatibleTargetForGenericSource = Target level ''{0}'' is incompatible with source level ''{1}''. A source level ''1.5'' or better is required
 configure.incompatibleComplianceForSource = Compliance level ''{0}'' is incompatible with source level ''{1}''. A compliance level ''{1}'' or better is required
@@ -261,9 +261,10 @@
 \    -15 -15.0          use 15  compliance (-source 15  -target 15)\n\
 \    -16 -16.0          use 16  compliance (-source 16  -target 16)\n\
 \    -17 -17.0          use 17  compliance (-source 17  -target 17)\n\
-\    -source <version>  set source level: 1.3 to 1.9, 10 to 17\n\
+\    -18 -18.0          use 18  compliance (-source 18  -target 18)\n\
+\    -source <version>  set source level: 1.3 to 1.9, 10 to 18\n\
 \                       (or 6, 6.0, etc)\n\
-\    -target <version>  set classfile target: 1.3 to 1.9, 10 to 17\n\
+\    -target <version>  set classfile target: 1.3 to 1.9, 10 to 18\n\
 \                       (or 6, 6.0, etc)\n\
 \                       cldc1.1 can also be used to generate the StackMap\n\
 \                       attribute\n\
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
index 4ac4566..b44aeb5 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2021 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -18,6 +18,7 @@
  *								Bug 400874 - [1.8][compiler] Inference infrastructure should evolve to meet JLS8 18.x (Part G of JSR335 spec)
  *     Gábor Kövesdán - Contribution for Bug 350000 - [content assist] Include non-prefix matches in auto-complete suggestions
  *     Microsoft Corporation - Contribution for bug 575562 - improve completion search performance
+ *     							Bug 578817 - skip the ignored types before creating CompletionProposals
  *******************************************************************************/
 package org.eclipse.jdt.internal.codeassist;
 
@@ -3112,6 +3113,8 @@
 		setSourceAndTokenRange(javadocTag.tagSourceStart, javadocTag.sourceEnd);
 		findJavadocBlockTags(javadocTag);
 		findJavadocInlineTags(javadocTag);
+		findJavadocInSnippetTags(javadocTag);
+
 	}
 	//TODO
 	private void completionOnJavadocTypeParamReference(ASTNode astNode) {
@@ -9338,6 +9341,36 @@
 		}
 	}
 
+	private void findJavadocInSnippetTags(CompletionOnJavadocTag javadocTag) {
+		char[][] possibleTags = javadocTag.getPossibleInSnippetTags();
+		if (possibleTags == null) return;
+		int length = possibleTags.length;
+		for (int i=0; i<length; i++) {
+			int relevance = computeBaseRelevance();
+			relevance += computeRelevanceForInterestingProposal();
+			relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for keywors
+
+			this.noProposal = false;
+			if (!this.requestor.isIgnored(CompletionProposal.JAVADOC_INLINE_TAG)) {
+				char[] possibleTag = possibleTags[i];
+				InternalCompletionProposal proposal =  createProposal(CompletionProposal.JAVADOC_BLOCK_TAG, this.actualCompletionPosition);
+				proposal.setName(possibleTag);
+				int tagLength = possibleTag.length;
+				char[] completion = new char[1+tagLength];
+				completion[0] = '@';
+				System.arraycopy(possibleTag, 0, completion, 1, tagLength);
+				proposal.setCompletion(completion);
+				proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+				proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
+				proposal.setRelevance(relevance);
+				this.requestor.accept(proposal);
+				if (DEBUG) {
+					this.printDebug(proposal);
+				}
+			}
+		}
+	}
+
 	/*
 	 * Find javadoc parameter names.
 	 */
@@ -14580,6 +14613,10 @@
 			typeCompletion = simpleTypeName;
 		}
 
+		if (this.requestor.isIgnored(fullyQualifiedName)) {
+			return;
+		}
+
 		ReferenceBinding typeBinding = this.lookupEnvironment.getType(CharOperation.splitOn('.', fullyQualifiedName));
 
 		int relevance = computeBaseRelevance();
@@ -14822,7 +14859,6 @@
 						proposal.setReplaceRange(this.endPosition - this.offset, this.endPosition - this.offset);
 						proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset);
 						proposal.setRelevance(relevance);
-
 						this.requestor.accept(proposal);
 						if(DEBUG) {
 							this.printDebug(proposal);
@@ -14887,6 +14923,9 @@
 			completionName = simpleTypeName;
 		}
 
+		if (this.requestor.isIgnored(fullyQualifiedName)) {
+			return;
+		}
 		TypeBinding guessedType = null;
 		if ((modifiers & ClassFileConstants.AccAnnotation) != 0 &&
 				this.assistNodeIsAnnotation &&
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionJavadocParser.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionJavadocParser.java
index e3ac263..a0fb28f 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionJavadocParser.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionJavadocParser.java
@@ -32,9 +32,13 @@
 @SuppressWarnings({"rawtypes", "unchecked"})
 public class CompletionJavadocParser extends JavadocParser {
 
+	boolean parsingSnippet=false;
+
 	// Initialize lengthes for block and inline tags tables
 	public final static int INLINE_ALL_TAGS_LENGTH;
 	public final static int BLOCK_ALL_TAGS_LENGTH;
+	public final static int SNIPPET_ALL_TAGS_LENGTH;
+
 	static {
 		int length = 0;
 		for (int i=0; i<INLINE_TAGS_LENGTH; i++) {
@@ -46,11 +50,17 @@
 			length += BLOCK_TAGS[i].length;
 		}
 		BLOCK_ALL_TAGS_LENGTH = length;
+		length = 0;
+		for (int i=0; i<SNIPPET_TAGS_LENGTH; i++) {
+			length += IN_SNIPPET_TAGS[i].length;
+		}
+		SNIPPET_ALL_TAGS_LENGTH = length;
+		//IN_SNIPPET_TAGS
 	}
 
 	// Level tags are array of inline/block tags depending on compilation source level
-	char[][][] levelTags = new char[2][][];
-	int[] levelTagsLength = new int[2];
+	char[][][] levelTags = new char[3][][];
+	int[] levelTagsLength = new int[3];
 
 	// Completion specific info
 	int cursorLocation;
@@ -329,14 +339,27 @@
 	/*
 	 * Get possible tags for a given prefix.
 	 */
-	private char[][][] possibleTags(char[] prefix, boolean newLine) {
-		char[][][] possibleTags = new char[2][][];
-		if (newLine) {
+	private char[][][] possibleTags(char[] prefix, boolean newLine, boolean inSnippet) {
+		char[][][] possibleTags = new char[3][][];
+		if (newLine && inSnippet == false) {
 			System.arraycopy(this.levelTags[BLOCK_IDX], 0, possibleTags[BLOCK_IDX] = new char[this.levelTagsLength[BLOCK_IDX]][], 0, this.levelTagsLength[BLOCK_IDX]);
 		} else {
 			possibleTags[BLOCK_IDX] = CharOperation.NO_CHAR_CHAR;
 		}
-		System.arraycopy(this.levelTags[INLINE_IDX], 0, possibleTags[INLINE_IDX] = new char[this.levelTagsLength[INLINE_IDX]][], 0, this.levelTagsLength[INLINE_IDX]);
+		if(inSnippet==false) {
+			System.arraycopy(this.levelTags[INLINE_IDX], 0, possibleTags[INLINE_IDX] = new char[this.levelTagsLength[INLINE_IDX]][], 0, this.levelTagsLength[INLINE_IDX]);
+		}
+		else {
+			possibleTags[INLINE_IDX] = CharOperation.NO_CHAR_CHAR;
+		}
+
+		if(inSnippet) {
+			System.arraycopy(this.levelTags[SNIPPET_IDX], 0, possibleTags[SNIPPET_IDX] = new char[this.levelTagsLength[SNIPPET_IDX]][], 0, this.levelTagsLength[SNIPPET_IDX]);
+
+		}
+		else {
+			possibleTags[SNIPPET_IDX] = CharOperation.NO_CHAR_CHAR;
+		}
 		if (prefix == null || prefix.length == 0) return possibleTags;
 		int kinds = this.levelTags.length;
 		for (int k=0; k<kinds; k++) {
@@ -393,15 +416,30 @@
 		if (this.levelTagsLength[INLINE_IDX] < INLINE_ALL_TAGS_LENGTH) {
 			System.arraycopy(this.levelTags[INLINE_IDX], 0, this.levelTags[INLINE_IDX] = new char[this.levelTagsLength[INLINE_IDX]][], 0, this.levelTagsLength[INLINE_IDX]);
 		}
+		// Init inline tags
+		this.levelTags[SNIPPET_IDX] = new char[SNIPPET_ALL_TAGS_LENGTH][];
+		this.levelTagsLength[SNIPPET_IDX]= 0;
+		for (int i=0; i< 1; i++) {// since only in java 18
+			int length = IN_SNIPPET_TAGS[i].length;
+			System.arraycopy(IN_SNIPPET_TAGS[i], 0, this.levelTags[SNIPPET_IDX], this.levelTagsLength[SNIPPET_IDX], length);
+			this.levelTagsLength[SNIPPET_IDX] += length;
+		}
+		if (this.levelTagsLength[SNIPPET_IDX] < INLINE_ALL_TAGS_LENGTH) {
+			System.arraycopy(this.levelTags[SNIPPET_IDX], 0, this.levelTags[SNIPPET_IDX] = new char[this.levelTagsLength[SNIPPET_IDX]][], 0, this.levelTagsLength[SNIPPET_IDX]);
+		}
+	}
+	@Override
+	protected Object parseArguments(Object receiver) throws InvalidInputException {
+		return parseArguments(receiver, true);
 	}
 	/*
 	 * Parse argument in @see tag method reference
 	 */
 	@Override
-	protected Object parseArguments(Object receiver) throws InvalidInputException {
+	protected Object parseArguments(Object receiver, boolean verifySpaceOrEndComment) throws InvalidInputException {
 
 		if (this.tagSourceStart>this.cursorLocation) {
-			return super.parseArguments(receiver);
+			return super.parseArguments(receiver, verifySpaceOrEndComment);
 		}
 
 		// Init
@@ -648,7 +686,13 @@
 	protected boolean parseTag(int previousPosition) throws InvalidInputException {
 		int startPosition = this.inlineTagStarted ? this.inlineTagStart : previousPosition;
 		boolean newLine = !this.lineStarted;
-		boolean valid = super.parseTag(previousPosition);
+		boolean valid = false;
+		try {
+			valid = super.parseTag(previousPosition);
+		}
+		catch (InvalidCursorLocation e) {
+			// catch exception and get a javadoc tag in snippet if possible
+		}
 		boolean inCompletion = (this.tagSourceStart <= (this.cursorLocation+1) && this.cursorLocation <= this.tagSourceEnd) // completion cursor is between first and last stacked identifiers
 			|| ((this.tagSourceStart == (this.tagSourceEnd+1) && this.tagSourceEnd == this.cursorLocation)); // or it's a completion on empty token
 		if (inCompletion) {
@@ -660,7 +704,7 @@
 			int length = this.cursorLocation+1-this.tagSourceStart;
 			char[] tag = new char[length];
 			System.arraycopy(this.source, this.tagSourceStart, tag, 0, length);
-			char[][][] tags = possibleTags(tag, newLine);
+			char[][][] tags = this.parsingSnippet ?  possibleTags(tag, false,true) : possibleTags(tag, newLine,false);
 			if (tags != null) {
 				this.completionNode = new CompletionOnJavadocTag(tag, position, startPosition, end, tags, this.allPossibleTags);
 			}
@@ -669,6 +713,16 @@
 	}
 
 	@Override
+	protected boolean parseSnippet() throws InvalidInputException {
+		this.parsingSnippet = true;
+		return super.parseSnippet();
+	}
+
+	@Override
+	protected boolean lookForTagsInSnippets() {
+		return this.parsingSnippet;
+	}
+	@Override
 	protected boolean parseThrows() {
 		try {
 			Object typeRef = parseQualifiedName(true);
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeDetector.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeDetector.java
index 6aeda7a..479cb6a 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeDetector.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeDetector.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2021 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -166,6 +166,10 @@
 		endVisit(fieldReference);
 	}
 	@Override
+	public void endVisit(GuardedPattern guardedPattern, BlockScope scope) {
+		endVisit(guardedPattern);
+	}
+	@Override
 	public void endVisit(IfStatement ifStatement, BlockScope scope) {
 		this.interestingEnclosings.pop();
 	}
@@ -360,6 +364,10 @@
 		return this.visit(fieldReference);
 	}
 	@Override
+	public boolean visit(GuardedPattern guardedPattern, BlockScope scope) {
+		return this.visit(guardedPattern);
+	}
+	@Override
 	public boolean visit(IfStatement ifStatement, BlockScope scope) {
 		this.interestingEnclosings.push(ifStatement);
 		return true;
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 0faab36..8af4475 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
@@ -75,6 +75,19 @@
 				output.append('\n');
 			}
 		}
+		// Print snippet tags
+		char[][] snipTags = this.possibleTags[SNIPPET_IDX];
+		if (snipTags != null) {
+			int length=snipTags.length;
+			if (length > 0) {
+				output.append("\npossible snippet tags:"); //$NON-NLS-1$
+				for (int i=0; i<length; i++) {
+					output.append("\n	- "); //$NON-NLS-1$
+					output.append(snipTags[i]);
+				}
+				output.append('\n');
+			}
+		}
 		return output.append('>');
 	}
 
@@ -178,4 +191,7 @@
 	public char[][] getPossibleInlineTags() {
 		return this.possibleTags[INLINE_IDX];
 	}
+	public char[][] getPossibleInSnippetTags() {
+		return this.possibleTags[SNIPPET_IDX];
+	}
 }
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 6d7a429..c809b6c 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
@@ -841,9 +841,16 @@
 		int length = this.expressionLengthPtr >= 0 ?
 				this.expressionLengthStack[this.expressionLengthPtr] : 0;
 		if (length > 0) {
-			InstanceOfExpression exp = (InstanceOfExpression) this.expressionStack[this.expressionPtr];
-			if (exp.elementVariable != null) {
-				pushOnAstStack(exp.elementVariable);
+			Expression exp = this.expressionStack[this.expressionPtr];
+			LocalDeclaration local = null;
+			if (exp instanceof InstanceOfExpression) {
+				local = ((InstanceOfExpression) exp).elementVariable;
+			} else if (exp instanceof AND_AND_Expression) {
+				InstanceOfExpression insExpr = (InstanceOfExpression) ((AND_AND_Expression) exp).left;
+				local = insExpr.elementVariable;
+			}
+			if (local != null) {
+				pushOnAstStack(local);
 			}
 		}
 	} else {
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 d1c5a08..ab436f6 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
@@ -1231,6 +1231,18 @@
 	int JavadocInvalidModuleQualification = Javadoc + Internal + 1810;
 	/** @since 3.29*/
 	int JavadocInvalidModule = Javadoc + Internal + 1811;
+	/** @since 3.30*/
+	int JavadocInvalidSnippet = Javadoc + Internal + 1812;
+	/** @since 3.30 */
+	int JavadocInvalidSnippetMissingColon = Javadoc + Internal + 1813;
+	/** @since 3.30 */
+	int JavadocInvalidSnippetContentNewLine = Javadoc + Internal + 1814;
+	/** @since 3.30 */
+	int JavadocInvalidSnippetRegionNotClosed = Javadoc + Internal + 1815;
+	/** @since 3.30 */
+	int JavadocInvalidSnippetRegexSubstringTogether = Javadoc + Internal + 1816;
+	/** @since 3.30 */
+	int JavadocInvalidSnippetDuplicateRegions = Javadoc + Internal + 1817;
 
 	/**
 	 * Generics
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
index d048af5..e7d8c3d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2021 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -70,6 +70,7 @@
 import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
+import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
 import org.eclipse.jdt.internal.compiler.ast.OpensStatement;
 import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
 import org.eclipse.jdt.internal.compiler.ast.Receiver;
@@ -213,7 +214,8 @@
 	public static final String METAFACTORY_STRING = new String(ConstantPool.METAFACTORY);
 	public static final String BOOTSTRAP_STRING = new String(ConstantPool.BOOTSTRAP);
 	public static final String TYPESWITCH_STRING = new String(ConstantPool.TYPESWITCH);
-	public static final String[] BOOTSTRAP_METHODS = {ALTMETAFACTORY_STRING, METAFACTORY_STRING, BOOTSTRAP_STRING, TYPESWITCH_STRING};
+	public static final String ENUMSWITCH_STRING = new String(ConstantPool.ENUMSWITCH);
+	public static final String[] BOOTSTRAP_METHODS = {ALTMETAFACTORY_STRING, METAFACTORY_STRING, BOOTSTRAP_STRING, TYPESWITCH_STRING, ENUMSWITCH_STRING};
 
 	/**
 	 * INTERNAL USE-ONLY
@@ -3759,7 +3761,12 @@
 			} else if (o instanceof TypeDeclaration) {
 				localContentsOffset = addBootStrapRecordEntry(localContentsOffset, (TypeDeclaration) o, fPtr);
 			} else if (o instanceof SwitchStatement) {
-				localContentsOffset = addBootStrapTypeSwitchEntry(localContentsOffset, (SwitchStatement) o, fPtr);
+				SwitchStatement stmt = (SwitchStatement) o;
+				if (stmt.expression.resolvedType.isEnum()) {
+					localContentsOffset = addBootStrapEnumSwitchEntry(localContentsOffset, stmt, fPtr);
+				} else {
+					localContentsOffset = addBootStrapTypeSwitchEntry(localContentsOffset, stmt, fPtr);
+				}
 			}
 		}
 
@@ -3957,7 +3964,7 @@
 		if (indexFortypeSwitch == 0) {
 			ReferenceBinding javaLangRuntimeSwitchBootstraps = this.referenceBinding.scope.getJavaLangRuntimeSwitchBootstraps();
 			indexFortypeSwitch = this.constantPool.literalIndexForMethodHandle(ClassFileConstants.MethodHandleRefKindInvokeStatic, javaLangRuntimeSwitchBootstraps,
-					ConstantPool.TYPESWITCH, ConstantPool.JAVA_LANG_RUNTIME_SWITCHBOOTSTRAPS_TYPESWITCH_SIGNATURE, false);
+					ConstantPool.TYPESWITCH, ConstantPool.JAVA_LANG_RUNTIME_SWITCHBOOTSTRAPS_SWITCH_SIGNATURE, false);
 			fPtr.put(ClassFile.TYPESWITCH_STRING, indexFortypeSwitch);
 		}
 		this.contents[localContentsOffset++] = (byte) (indexFortypeSwitch >> 8);
@@ -3967,24 +3974,65 @@
 		int numArgsLocation = localContentsOffset;
 		CaseStatement.ResolvedCase[] constants = switchStatement.otherConstants;
 		int numArgs = constants.length;
+		if (switchStatement.containsNull) --numArgs;
+		this.contents[numArgsLocation++] = (byte) (numArgs >> 8);
+		this.contents[numArgsLocation] = (byte) numArgs;
+		localContentsOffset += 2;
+
+		for (CaseStatement.ResolvedCase c : constants) {
+			if (c.isPattern()) {
+				char[] typeName = c.t.constantPoolName();
+				int typeIndex = this.constantPool.literalIndexForType(typeName);
+				this.contents[localContentsOffset++] = (byte) (typeIndex >> 8);
+				this.contents[localContentsOffset++] = (byte) typeIndex;
+			} else if ((c.e instanceof StringLiteral)||(c.c instanceof StringConstant)) {
+				int intValIdx =
+						this.constantPool.literalIndex(c.c.stringValue());
+				this.contents[localContentsOffset++] = (byte) (intValIdx >> 8);
+				this.contents[localContentsOffset++] = (byte) intValIdx;
+			} else {
+				if (c.e instanceof NullLiteral) continue;
+				int intValIdx =
+						this.constantPool.literalIndex(c.intValue());
+				this.contents[localContentsOffset++] = (byte) (intValIdx >> 8);
+				this.contents[localContentsOffset++] = (byte) intValIdx;
+			}
+		}
+
+		return localContentsOffset;
+	}
+	private int addBootStrapEnumSwitchEntry(int localContentsOffset, SwitchStatement switchStatement, Map<String, Integer> fPtr) {
+		final int contentsEntries = 10;
+		int indexForenumSwitch = fPtr.get(ClassFile.ENUMSWITCH_STRING);
+		if (contentsEntries + localContentsOffset >= this.contents.length) {
+			resizeContents(contentsEntries);
+		}
+		if (indexForenumSwitch == 0) {
+			ReferenceBinding javaLangRuntimeSwitchBootstraps = this.referenceBinding.scope.getJavaLangRuntimeSwitchBootstraps();
+			indexForenumSwitch = this.constantPool.literalIndexForMethodHandle(ClassFileConstants.MethodHandleRefKindInvokeStatic, javaLangRuntimeSwitchBootstraps,
+					ConstantPool.ENUMSWITCH, ConstantPool.JAVA_LANG_RUNTIME_SWITCHBOOTSTRAPS_SWITCH_SIGNATURE, false);
+			fPtr.put(ClassFile.ENUMSWITCH_STRING, indexForenumSwitch);
+		}
+		this.contents[localContentsOffset++] = (byte) (indexForenumSwitch >> 8);
+		this.contents[localContentsOffset++] = (byte) indexForenumSwitch;
+
+		// u2 num_bootstrap_arguments
+		int numArgsLocation = localContentsOffset;
+		CaseStatement.ResolvedCase[] constants = switchStatement.otherConstants;
+		int numArgs = constants.length;
 		this.contents[numArgsLocation++] = (byte) (numArgs >> 8);
 		this.contents[numArgsLocation] = (byte) numArgs;
 		localContentsOffset += 2;
 
 		for (CaseStatement.ResolvedCase c : constants) {
 			if (c.isPattern()) {
-				char[] typeName = c.t.constantPoolName();
+				char[] typeName = switchStatement.expression.resolvedType.constantPoolName();
 				int typeIndex = this.constantPool.literalIndexForType(typeName);
 				this.contents[localContentsOffset++] = (byte) (typeIndex >> 8);
 				this.contents[localContentsOffset++] = (byte) typeIndex;
-			} else if (c.e instanceof StringLiteral) {
-				int intValIdx =
-						this.constantPool.literalIndex(c.c.stringValue());
-				this.contents[localContentsOffset++] = (byte) (intValIdx >> 8);
-				this.contents[localContentsOffset++] = (byte) intValIdx;
 			} else {
 				int intValIdx =
-						this.constantPool.literalIndex(c.intValue());
+						this.constantPool.literalIndex(c.e.toString());
 				this.contents[localContentsOffset++] = (byte) (intValIdx >> 8);
 				this.contents[localContentsOffset++] = (byte) intValIdx;
 			}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CaseStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CaseStatement.java
index c274b97..604f51f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CaseStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CaseStatement.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2021 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -81,7 +81,7 @@
 				if (!(i == nullPatternCount && e instanceof TypePattern))
 					currentScope.problemReporter().IllegalFallThroughToPattern(e);
 			}
-			analyseConstantExpression(currentScope, flowContext, flowInfo, e);
+			flowInfo = analyseConstantExpression(currentScope, flowContext, flowInfo, e);
 			if (nullPatternCount > 0 && e instanceof TypePattern) {
 				LocalVariableBinding binding = ((TypePattern) e).local.binding;
 				if (binding != null)
@@ -91,7 +91,7 @@
 	}
 	return flowInfo;
 }
-private void analyseConstantExpression(
+private FlowInfo analyseConstantExpression(
 		BlockScope currentScope,
 		FlowContext flowContext,
 		FlowInfo flowInfo,
@@ -110,7 +110,7 @@
 			}
 		}
 	}
-	e.analyseCode(currentScope, flowContext, flowInfo);
+	return e.analyseCode(currentScope, flowContext, flowInfo);
 }
 
 @Override
@@ -176,12 +176,14 @@
 	public Constant c;
 	public Expression e;
 	public TypeBinding t; // For ease of access. This.e contains the type binding anyway.
+	public int index;
 	private int intValue;
 	private boolean isPattern;
-	ResolvedCase(Constant c, Expression e, TypeBinding t) {
+	ResolvedCase(Constant c, Expression e, TypeBinding t, int index) {
 		this.c = c;
 		this.e = e;
 		this.t= t;
+		this.index = index;
 		if (c.typeID() == TypeIds.T_JavaLangString) {
 			c.stringValue().hashCode();
 		} else {
@@ -344,7 +346,9 @@
 		if (caseType.isValidBinding()) {
 			Constant con = resolveConstantExpression(scope, caseType, switchExpressionType, switchStatement, e);
 			if (con != Constant.NotAConstant) {
-				cases.add(new ResolvedCase(con, e, caseType));
+				int index = this == switchStatement.nullCase && e instanceof NullLiteral ?
+						-1 : switchStatement.constantIndex++;
+				cases.add(new ResolvedCase(con, e, caseType, index));
 			}
 		}
 	}
@@ -446,7 +450,7 @@
 	Constant constant = Constant.NotAConstant;
 	TypeBinding type = e.resolveType(scope);
 	if (type != null) {
-		constant = IntConstant.fromValue(switchStatement.caseLabelElements.size());
+		constant = IntConstant.fromValue(switchStatement.constantIndex);
 		switchStatement.caseLabelElements.add(e);
 		if (e.resolvedType != null) {
 			// 14.30.2 at compile-time we "resolve" the pattern with respect to the (compile-time) type
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java
index 1f2aa27..64fe740 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java
@@ -42,6 +42,7 @@
 import org.eclipse.jdt.internal.compiler.lookup.Binding;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.CaptureBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ImplicitNullAnnotationVerifier;
 import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
 import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
@@ -143,6 +144,7 @@
 				ReferenceBinding iterator = currentScope.getJavaUtilIterator();
 				if (iterator != null) {
 					MethodBinding next = iterator.getExactMethod(TypeConstants.NEXT, Binding.NO_TYPES, currentScope.compilationUnitScope);
+					ImplicitNullAnnotationVerifier.ensureNullnessIsKnown(next, currentScope);
 					if (next != null && ((next.tagBits & TagBits.AnnotationNullMASK) != 0)) {
 						nullStatus = FlowInfo.tagBitsToNullStatus(next.tagBits);
 					}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/GuardedPattern.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/GuardedPattern.java
index 7eb63f1..7472546 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/GuardedPattern.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/GuardedPattern.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2021 IBM Corporation and others.
+ * Copyright (c) 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -28,6 +28,8 @@
 	public Pattern primaryPattern;
 	public Expression condition;
 	/* package */ BranchLabel thenTarget;
+	int thenInitStateIndex1 = -1;
+	int thenInitStateIndex2 = -1;
 
 	public GuardedPattern(Pattern primaryPattern, Expression conditionalAndExpression) {
 		this.primaryPattern = primaryPattern;
@@ -51,7 +53,11 @@
 	@Override
 	public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
 		flowInfo = this.primaryPattern.analyseCode(currentScope, flowContext, flowInfo);
-		return this.condition.analyseCode(currentScope, flowContext, flowInfo);
+		this.thenInitStateIndex1 = currentScope.methodScope().recordInitializationStates(flowInfo);
+		FlowInfo mergedFlow = this.condition.analyseCode(currentScope, flowContext, flowInfo);
+		mergedFlow = mergedFlow.safeInitsWhenTrue();
+		this.thenInitStateIndex2 = currentScope.methodScope().recordInitializationStates(mergedFlow);
+		return mergedFlow;
 	}
 
 	@Override
@@ -60,19 +66,29 @@
 
 		Constant cst =  this.condition.optimizedBooleanConstant();
 		this.thenTarget = new BranchLabel(codeStream);
-
 		this.condition.generateOptimizedBoolean(
 				currentScope,
 				codeStream,
 				this.thenTarget,
 				null,
 				cst == Constant.NotAConstant);
+		if (this.thenInitStateIndex2 != -1) {
+			codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.thenInitStateIndex2);
+			codeStream.addDefinitelyAssignedVariables(currentScope, this.thenInitStateIndex2);
+		}
 	}
 
+	public boolean isGuardTrueAlways() {
+		Constant cst = this.condition.optimizedBooleanConstant();
+		return cst != Constant.NotAConstant && cst.booleanValue() == true;
+	}
 	@Override
 	public boolean isTotalForType(TypeBinding type) {
-		Constant cst = this.condition.optimizedBooleanConstant();
-		return this.primaryPattern.isTotalForType(type) && cst != Constant.NotAConstant && cst.booleanValue() == true;
+		return this.primaryPattern.isTotalForType(type) && isGuardTrueAlways();
+	}
+	@Override
+	public Pattern primary() {
+		return this.primaryPattern;
 	}
 
 	@Override
@@ -92,13 +108,15 @@
 			return this.resolvedType;
 		this.resolvedType = this.primaryPattern.resolveType(scope);
 		this.condition.resolveType(scope);
+		LocalDeclaration PatternVar = this.primaryPattern.getPatternVariableIntroduced();
+		LocalVariableBinding lvb = PatternVar.binding;
 		this.condition.traverse(new ASTVisitor() {
 			@Override
 			public boolean visit(
 					SingleNameReference ref,
 					BlockScope skope) {
 				LocalVariableBinding local = ref.localVariableBinding();
-				if (local != null) {
+				if (local != null && local != lvb) {
 					ref.bits |= ASTNode.IsUsedInPatternGuard;
 				}
 				return false;
@@ -133,4 +151,10 @@
 		}
 		visitor.endVisit(this, scope);
 	}
+	public void suspendVariables(CodeStream codeStream, BlockScope scope) {
+		codeStream.removeNotDefinitelyAssignedVariables(scope, this.thenInitStateIndex1);
+	}
+	public void resumeVariables(CodeStream codeStream, BlockScope scope) {
+		codeStream.addDefinitelyAssignedVariables(scope, this.thenInitStateIndex2);
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Pattern.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Pattern.java
index 9338f4d..abf299a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Pattern.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Pattern.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2021 IBM Corporation and others.
+ * Copyright (c) 2021, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -37,6 +37,10 @@
 
 	public abstract boolean dominates(Pattern p);
 
+	public Pattern primary() {
+		return this;
+	}
+
 	@Override
 	public StringBuffer print(int indent, StringBuffer output) {
 		return this.printExpression(indent, output);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
index 50e5ff0..11b592c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
@@ -169,8 +169,12 @@
 			}
 			if (flowInfo.isPotentiallyAssigned(localBinding) || (this.bits & ASTNode.IsCapturedOuterLocal) != 0) {
 				localBinding.tagBits &= ~TagBits.IsEffectivelyFinal;
-				if (!isFinal && (this.bits & ASTNode.IsCapturedOuterLocal) != 0) {
-					currentScope.problemReporter().cannotReferToNonEffectivelyFinalOuterLocal(localBinding, this);
+				if (!isFinal) {
+					if ((this.bits & ASTNode.IsCapturedOuterLocal) != 0) {
+						currentScope.problemReporter().cannotReferToNonEffectivelyFinalOuterLocal(localBinding, this);
+					} else if ((this.bits & ASTNode.IsUsedInPatternGuard) != 0) {
+						currentScope.problemReporter().cannotReferToNonFinalLocalInGuard(localBinding, this);
+					}
 				}
 			}
 			if (! isFinal && (localBinding.tagBits & TagBits.IsEffectivelyFinal) != 0 && (localBinding.tagBits & TagBits.IsArgument) == 0) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java
index f8c5377..c469b28 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2021 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -21,7 +21,9 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.function.Function;
 import java.util.function.IntPredicate;
 
@@ -46,6 +48,7 @@
 import org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding;
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
 import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
+import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
 
 @SuppressWarnings("rawtypes")
@@ -71,7 +74,7 @@
 	public boolean containsPatterns;
 	public boolean containsNull;
 	private BranchLabel switchPatternRestartTarget;
-	/* package */ Pattern totalPattern;
+	/* package */ public Pattern totalPattern;
 
 	// fallthrough
 	public final static int CASE = 0;
@@ -108,6 +111,7 @@
 	/* package */ boolean isNonTraditional = false;
 	/* package */ List<Pattern> caseLabelElements = new ArrayList<>(0);//TODO: can we remove this?
 	public List<TypeBinding> caseLabelElementTypes = new ArrayList<>(0);
+	int constantIndex = 0;
 
 	protected int getFallThroughState(Statement stmt, BlockScope blockScope) {
 		if ((this.switchBits & LabeledRules) != 0) {
@@ -515,6 +519,7 @@
 			if (this.containsPatterns) {
 				generateCodeSwitchPatternPrologue(currentScope, codeStream);
 				valueRequired = true;
+				transformConstants();
 			} else if (resolvedType1.isEnum()) {
 				// go through the translation table
 				codeStream.invoke(Opcodes.OPC_invokestatic, this.synthetic, null /* default declaringClass */);
@@ -572,6 +577,7 @@
 
 			// generate the switch block statements
 			int caseIndex = 0;
+			int typeSwitchIndex = 0;
 			if (this.statements != null) {
 				for (int i = 0, maxCases = this.statements.length; i < maxCases; i++) {
 					Statement statement = this.statements[i];
@@ -584,16 +590,20 @@
 						caseStatement = (CaseStatement) statement;
 						patternCaseExitPreviousCaseScope(codeStream, caseIndex);
 						caseIndex++;
+						typeSwitchIndex += caseStatement.constantExpressions.length;
 					} else {
 						if (statement == this.defaultCase) { // statements[i] is a case or a default case
 							this.scope.enclosingCase = this.defaultCase; // record entering in a switch case block
 							if (this.preSwitchInitStateIndex != -1) {
 								codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preSwitchInitStateIndex);
 							}
+						} else if (statement instanceof CaseStatement) {
+							caseStatement = (CaseStatement) statement;
+							typeSwitchIndex += caseStatement.constantExpressions.length;
 						}
 					}
 					statementGenerateCode(currentScope, codeStream, statement);
-					generateCodePatternCaseEpilogue(codeStream, caseIndex, caseStatement);
+					generateCodePatternCaseEpilogue(codeStream, typeSwitchIndex, caseStatement);
 				}
 			}
 			boolean enumInSwitchExpression =  resolvedType1.isEnum() && this instanceof SwitchExpression;
@@ -657,6 +667,19 @@
 			if (this.scope != null) this.scope.enclosingCase = null; // no longer inside switch case block
 		}
 	}
+	private void transformConstants() {
+		if (this.nullCase == null) {
+			for (int i = 0,l = this.otherConstants.length; i < l; ++i) {
+				if (this.otherConstants[i].e == this.totalPattern) {
+					this.otherConstants[i].index = -1;
+					break;
+				}
+			}
+		}
+		for (int i = 0; i < this.constants.length; i++) {
+			this.constants[i] = this.otherConstants[i].index;
+		}
+	}
 	private void generateCodeSwitchPatternEpilogue(CodeStream codeStream) {
 		if (this.containsPatterns && this.caseLabelElements.size() > 0) {
 			codeStream.removeVariable(this.dispatchPatternCopy);
@@ -677,10 +700,15 @@
 				) {
 			Pattern pattern = (Pattern) caseStatement.constantExpressions[caseStatement.patternIndex];
 			if (pattern instanceof GuardedPattern) {
-				codeStream.loadInt(caseIndex);
-				codeStream.store(this.restartIndexLocal, false);
-				codeStream.goto_(this.switchPatternRestartTarget);
-				((GuardedPattern) pattern).thenTarget.place();
+				GuardedPattern guardedPattern = (GuardedPattern) pattern;
+				if (!guardedPattern.isGuardTrueAlways()) {
+					guardedPattern.suspendVariables(codeStream, this.scope);
+					codeStream.loadInt(caseIndex);
+					codeStream.store(this.restartIndexLocal, false);
+					codeStream.goto_(this.switchPatternRestartTarget);
+					guardedPattern.thenTarget.place();
+					guardedPattern.resumeVariables(codeStream, this.scope);
+				}
 			}
 		}
 	}
@@ -706,6 +734,13 @@
 		codeStream.load(this.dispatchPatternCopy);
 		codeStream.load(this.restartIndexLocal);
 		int invokeDynamicNumber = codeStream.classFile.recordBootstrapMethod(this);
+		if (this.expression.resolvedType.isEnum()) {
+			generateEnumSwitchPatternPrologue(codeStream, invokeDynamicNumber);
+		} else {
+			generateTypeSwitchPatternPrologue(codeStream, invokeDynamicNumber);
+		}
+	}
+	private void generateTypeSwitchPatternPrologue(CodeStream codeStream, int invokeDynamicNumber) {
 		codeStream.invokeDynamic(invokeDynamicNumber,
 				2, // Object, restartIndex
 				1, // int
@@ -714,6 +749,17 @@
 				TypeIds.T_int,
 				TypeBinding.INT);
 	}
+	private void generateEnumSwitchPatternPrologue(CodeStream codeStream, int invokeDynamicNumber) {
+		String genericTypeSignature = new String(this.expression.resolvedType.genericTypeSignature());
+		String callingParams = "(" + genericTypeSignature + "I)I"; //$NON-NLS-1$ //$NON-NLS-2$
+		codeStream.invokeDynamic(invokeDynamicNumber,
+				2, // Object, restartIndex
+				1, // int
+				"enumSwitch".toCharArray(), //$NON-NLS-1$
+				callingParams.toCharArray(),
+				TypeIds.T_int,
+				TypeBinding.INT);
+	}
 	protected void statementGenerateCode(BlockScope currentScope, CodeStream codeStream, Statement statement) {
 		statement.generateCode(this.scope, codeStream);
 	}
@@ -882,7 +928,11 @@
 									if (con.typeID() == TypeIds.T_JavaLangString) {
 										return c2.stringValue().equals(con.stringValue());
 									} else {
-										return (c2.typeID() == TypeIds.T_JavaLangString) ? false : c2.intValue() == c1;
+										if (c2.typeID() == TypeIds.T_JavaLangString)
+											return false;
+										if (con.intValue() == c2.intValue())
+											return true;
+										return this.constants[idx] == c1;
 									}
 								};
 								TypeBinding type = c.e.resolvedType;
@@ -899,13 +949,18 @@
 											if (type.isBaseType()) {
 												type = this.scope.environment().computeBoxingType(type);
 											}
-											if (p1.isTotalForType(type))
+											if (p1.primary().isTotalForType(type))
 												this.scope.problemReporter().patternDominatedByAnother(c.e);
 										}
 									}
 								} else {
 									if (!c.isPattern() && check.test(j)) {
 										if (this.isNonTraditional) {
+											boolean reportDup = true;
+											if (c.e instanceof NullLiteral || this.otherConstants[j].e instanceof NullLiteral) {
+												reportDup = c.e instanceof NullLiteral && this.otherConstants[j].e instanceof NullLiteral;
+											}
+											if (reportDup)
 											reportDuplicateCase(c.e, this.otherConstants[j].e, length);
 										} else {
 											reportDuplicateCase(caseStmt, this.cases[caseIndex[j]], length);
@@ -937,8 +992,8 @@
 			reportMixingCaseTypes();
 
 			// check default case for all kinds of switch:
-			checkAndFlagDefaultSealed(upperScope, compilerOptions);
-			if (this.defaultCase == null) {
+			boolean flagged = checkAndFlagDefaultSealed(upperScope, compilerOptions);
+			if (!flagged && this.defaultCase == null) {
 				if (ignoreMissingDefaultCase(compilerOptions, isEnumSwitch) && isEnumSwitch) {
 						upperScope.methodScope().hasMissingSwitchDefault = true;
 				} else {
@@ -1015,27 +1070,107 @@
 		}
 		return false;
 	}
-	private void checkAndFlagDefaultSealed(BlockScope skope, CompilerOptions compilerOptions) {
+	private boolean checkAndFlagDefaultSealed(BlockScope skope, CompilerOptions compilerOptions) {
 		if (this.defaultCase != null) { // mark covered as a side effect (since covers is intro in 406)
 			this.switchBits |= SwitchStatement.Exhaustive;
-			return;
+			return false;
 		}
 		boolean checkSealed = this.containsPatterns
 				&& JavaFeature.SEALED_CLASSES.isSupported(compilerOptions)
 				&& JavaFeature.PATTERN_MATCHING_IN_SWITCH.isSupported(compilerOptions)
-				&& this.expression.resolvedType instanceof ReferenceBinding
-				&& ((ReferenceBinding) this.expression.resolvedType).isSealed();
-		if (!checkSealed) return;
+				&& this.expression.resolvedType instanceof ReferenceBinding;
+		if (!checkSealed) return false;
 		ReferenceBinding ref = (ReferenceBinding) this.expression.resolvedType;
-		if (!ref.isSealed()) return;
-		List<TypeBinding> permittedTypes = Arrays.asList(ref.permittedTypes());
-		for (TypeBinding pt : permittedTypes) {
-			if (!this.caseLabelElementTypes.contains(pt)) {
-				skope.problemReporter().missingDefaultCase(this, false, ref);
-				return;
-			}
+		if (!(ref.isClass() || ref.isInterface() || ref.isTypeVariable() || ref.isIntersectionType()))
+			return false;
+		if (ref instanceof TypeVariableBinding) {
+			TypeVariableBinding tvb = (TypeVariableBinding) ref;
+			ref = tvb.firstBound instanceof ReferenceBinding ? (ReferenceBinding) tvb.firstBound : ref;
+		}
+		if (!ref.isSealed()) return false;
+		List<ReferenceBinding> allallowedTypes = new ArrayList<>();
+		if (ref.isClass() && !ref.isAbstract())
+			allallowedTypes.add(ref);
+
+		List<ReferenceBinding> permittedTypes = new ArrayList<>(Arrays.asList(ref.permittedTypes()));
+		allallowedTypes.addAll(permittedTypes);
+		if (!isExhaustiveWithCaseTypes(allallowedTypes, this.caseLabelElementTypes)) {
+			if (this instanceof SwitchExpression) // non-exhaustive switch expressions will be flagged later.
+				return false;
+			skope.problemReporter().enhancedSwitchMissingDefaultCase(this.expression);
+			return true;
 		}
 		this.switchBits |= SwitchStatement.Exhaustive;
+		return false;
+	}
+	private boolean isExhaustiveWithCaseTypes(List<ReferenceBinding> allallowedTypes,  List<TypeBinding> listedTypes) {
+		// first KISS (Keep It Simple Stupid)
+		int pendingTypes = allallowedTypes.size();
+		for (TypeBinding pt : allallowedTypes) {
+			for (TypeBinding type : listedTypes) {
+				if (pt.isCompatibleWith(type)) {
+					--pendingTypes;
+					break;
+				}
+			}
+		}
+		if (pendingTypes == 0)
+			return true;
+		// else - #KICKME (Keep It Complicated Keep Me Employed)"
+		List<TypeBinding> coveredTypes = new ArrayList<>(listedTypes);
+		List<ReferenceBinding> remainingTypes = new ArrayList<>(allallowedTypes);
+		remainingTypes.removeAll(coveredTypes);
+
+		Map<TypeBinding, List<TypeBinding>> impliedTypes = new HashMap<>();
+
+		for (ReferenceBinding type : remainingTypes) {
+			impliedTypes.put(type, new ArrayList<>());
+			List<ReferenceBinding> typesToAdd = new ArrayList<>();
+			for (ReferenceBinding impliedType : allallowedTypes) {
+				if (impliedType.equals(type)) continue;
+				if (type.isClass()) {
+					if (impliedType.isAbstract() && type.superclass().equals(impliedType)) {
+						typesToAdd.add(impliedType);
+					}
+					if (Arrays.asList(type.superInterfaces()).contains(impliedType))
+						typesToAdd.add(impliedType);
+				} else if (type.isInterface()) {
+					if (Arrays.asList(impliedType.superInterfaces()).contains(type))
+						typesToAdd.add(impliedType);
+				}
+			}
+			if (!typesToAdd.isEmpty()) {
+				impliedTypes.get(type).addAll(typesToAdd);
+			}
+		}
+		boolean delta = true;
+		while (delta) {
+			delta = false;
+			List<ReferenceBinding> typesToAdd = new ArrayList<>();
+			for (ReferenceBinding type : remainingTypes) {
+				boolean add = false;
+				if (type.isClass()) {
+					for (TypeBinding tb : impliedTypes.get(type)) {
+						if (coveredTypes.contains(tb)) {
+							add = true;
+							break;
+						}
+					}
+				} else if (type.isInterface()) {
+					add = coveredTypes.containsAll(impliedTypes.get(type));
+				}
+				if (add) {
+					typesToAdd.add(type);
+				}
+			}
+			if (!typesToAdd.isEmpty()) {
+				remainingTypes.removeAll(typesToAdd);
+				coveredTypes.addAll(typesToAdd);
+				typesToAdd.clear();
+				delta = true;
+			}
+		}
+		return remainingTypes.isEmpty();
 	}
 	private void addSecretPatternSwitchVariables(BlockScope upperScope) {
 		if (this.containsPatterns) {
@@ -1168,7 +1303,7 @@
 		if ((this.switchBits & LabeledRules) == 0) { // switch labeled statement group
 			if (this.statements[this.statements.length - 1].canCompleteNormally())
 				return true; // last statement as well as last switch label after blocks if exists.
-			if (this.defaultCase == null)
+			if (this.totalPattern == null && this.defaultCase == null)
 				return true;
 			for (int i = 0, length = this.statements.length; i < length; i++) {
 				if (this.statements[i].breaksOut(null))
@@ -1179,7 +1314,7 @@
 			for (Statement stmt : this.statements) {
 				if (stmt instanceof CaseStatement)
 					continue; // skip case
-				if (this.defaultCase == null)
+				if (this.totalPattern == null && this.defaultCase == null)
 					return true;
 				if (stmt instanceof Expression)
 					return true;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypePattern.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypePattern.java
index 57c6ca7..ca21799 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypePattern.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypePattern.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2021 IBM Corporation and others.
+ * Copyright (c) 2021, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -97,7 +97,7 @@
 	public boolean isTotalForType(TypeBinding type) {
 		if (type == null || this.resolvedType == null)
 			return false;
-		return (type.erasure().isSubtypeOf(this.resolvedType.erasure(), false));
+		return (type.isSubtypeOf(this.resolvedType, false));
 	}
 	@Override
 	public boolean dominates(Pattern p) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java
index ad2a814..94cd8d3 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2021 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -140,9 +140,10 @@
 	int MAJOR_VERSION_15 = 59;
 	int MAJOR_VERSION_16 = 60;
 	int MAJOR_VERSION_17 = 61;
+	int MAJOR_VERSION_18 = 62;
 
 	int MAJOR_VERSION_0 = 44;
-	int MAJOR_LATEST_VERSION = MAJOR_VERSION_17;
+	int MAJOR_LATEST_VERSION = MAJOR_VERSION_18;
 
 	int MINOR_VERSION_0 = 0;
 	int MINOR_VERSION_1 = 1;
@@ -170,6 +171,7 @@
 	long JDK15 = ((long)ClassFileConstants.MAJOR_VERSION_15 << 16) + ClassFileConstants.MINOR_VERSION_0;
 	long JDK16 = ((long)ClassFileConstants.MAJOR_VERSION_16 << 16) + ClassFileConstants.MINOR_VERSION_0;
 	long JDK17 = ((long)ClassFileConstants.MAJOR_VERSION_17 << 16) + ClassFileConstants.MINOR_VERSION_0;
+	long JDK18 = ((long)ClassFileConstants.MAJOR_VERSION_18 << 16) + ClassFileConstants.MINOR_VERSION_0;
 
 	public static long getLatestJDKLevel() {
 		return ((long)ClassFileConstants.MAJOR_LATEST_VERSION << 16) + ClassFileConstants.MINOR_VERSION_0;
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 13f51dc..2a190fd 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
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2021 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -7773,7 +7773,8 @@
 	this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_swap;
 }
 
-public void tableswitch(CaseLabel defaultLabel, int low, int high, int[] keys, int[] sortedIndexes, int[] mapping, CaseLabel[] casesLabel) {
+public void tableswitch(CaseLabel defaultLabel, int low, int high, int[] keys,
+		int[] sortedIndexes, int[] mapping, CaseLabel[] casesLabel) {
 	this.countLabels = 0;
 	this.stackDepth--;
 	popTypeBinding();
@@ -7798,12 +7799,13 @@
 	defaultLabel.branch();
 	writeSignedWord(low);
 	writeSignedWord(high);
-	int i = low, j = low;
+	int i = low, j = 0;
 	// the index j is used to know if the index i is one of the missing entries in case of an
 	// optimized tableswitch
+
 	while (true) {
-		int index;
-		int key = keys[index = sortedIndexes[j - low]];
+		int index = sortedIndexes[j];
+		int key = keys[index];
 		if (key == i) {
 			casesLabel[mapping[index]].branch();
 			j++;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java
index 9ffca87..6a59b13 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2021 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -313,7 +313,8 @@
 	public static final char[] JAVA_LANG_RUNTIME_OBJECTMETHOD_BOOTSTRAP_SIGNATURE = "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/TypeDescriptor;Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/invoke/MethodHandle;)Ljava/lang/Object;".toCharArray(); //$NON-NLS-1$
 	public static final char[] PREVIEW_FEATURE = "/PreviewFeature".toCharArray(); //$NON-NLS-1$
 	public static final char[] TYPESWITCH = "typeSwitch".toCharArray(); //$NON-NLS-1$
-	public static final char[] JAVA_LANG_RUNTIME_SWITCHBOOTSTRAPS_TYPESWITCH_SIGNATURE = "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;".toCharArray(); //$NON-NLS-1$
+	public static final char[] ENUMSWITCH = "enumSwitch".toCharArray(); //$NON-NLS-1$
+	public static final char[] JAVA_LANG_RUNTIME_SWITCHBOOTSTRAPS_SWITCH_SIGNATURE = "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;".toCharArray(); //$NON-NLS-1$
 
 	/**
 	 * ConstantPool constructor comment.
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
index 997ff4a..c2c278e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2021 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -326,6 +326,7 @@
 	public static final String VERSION_15 = "15"; //$NON-NLS-1$
 	public static final String VERSION_16 = "16"; //$NON-NLS-1$
 	public static final String VERSION_17 = "17"; //$NON-NLS-1$
+	public static final String VERSION_18 = "18"; //$NON-NLS-1$
 	/*
 	 * Note: Whenever a new version is added, make sure getLatestVersion()
 	 * is updated with it.
@@ -754,7 +755,7 @@
 	 * Return the latest Java language version supported by the Eclipse compiler
 	 */
 	public static String getLatestVersion() {
-		return VERSION_17;
+		return VERSION_18;
 	}
 	/**
 	 * Return the most specific option key controlling this irritant. Note that in some case, some irritant is controlled by
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/JavaFeature.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/JavaFeature.java
index f0ad92a..529d240 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/JavaFeature.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/JavaFeature.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2020, 2021 IBM Corporation and others.
+ * Copyright (c) 2020, 2022 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
@@ -57,7 +57,7 @@
 			Messages.bind(Messages.sealed_types),
 			new char[][] {TypeConstants.SEALED, TypeConstants.PERMITS},
 			false),
-	PATTERN_MATCHING_IN_SWITCH(ClassFileConstants.JDK17,
+	PATTERN_MATCHING_IN_SWITCH(ClassFileConstants.JDK18,
 			Messages.bind(Messages.pattern_matching_switch),
 			new char[][] {},
 			true),
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
index 021766d..36ed7ed 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
@@ -265,7 +265,7 @@
 	if (binaryValue instanceof EnumConstantSignature) {
 		EnumConstantSignature ref = (EnumConstantSignature) binaryValue;
 		ReferenceBinding enumType = (ReferenceBinding) env.getTypeFromSignature(ref.getTypeName(), 0, -1, false, null, missingTypeNames, ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER);
-		if (enumType.isUnresolvedType() && !resolveEnumConstants)
+		if ((enumType.isUnresolvedType() || !enumType.isFieldInitializationFinished()) && !resolveEnumConstants)
 			return new ElementValuePair.UnresolvedEnumConstant(enumType, env, ref.getEnumConstantName());
 		enumType = (ReferenceBinding) resolveType(enumType, env, false /* no raw conversion */);
 		return enumType.getField(ref.getEnumConstantName(), false);
@@ -804,13 +804,11 @@
 			if (binaryType.isRecord()) {
 				iComponents = binaryType.getRecordComponents();
 				if (iComponents != null) {
-					VariableBinding[] createFields = createFields(iComponents, binaryType, sourceLevel, missingTypeNames, true);
-					this.components = (RecordComponentBinding[]) createFields;
+					createFields(iComponents, binaryType, sourceLevel, missingTypeNames, RECORD_INITIALIZATION);
 				}
 			}
 			IBinaryField[] iFields = binaryType.getFields();
-			VariableBinding[] createdFields = createFields(iFields, binaryType, sourceLevel, missingTypeNames, false);
-			this.fields = (FieldBinding[]) createdFields;
+			createFields(iFields, binaryType, sourceLevel, missingTypeNames, FIELD_INITIALIZATION);
 			IBinaryMethod[] iMethods = createMethods(binaryType.getMethods(), binaryType, sourceLevel, missingTypeNames);
 			boolean isViewedAsDeprecated = isViewedAsDeprecated();
 			if (isViewedAsDeprecated) {
@@ -849,6 +847,8 @@
 				if (iMethods != null) {
 					for (int i = 0; i < iMethods.length; i++) {
 						// below 1.8 we still might use an annotation walker to discover external annotations:
+						// (not using walker, which has defaultNullness, because defaults on parameters & return will be applied
+						//  by ImplicitNullAnnotationVerifier, triggered per invocation via MessageSend.resolveType() et al)
 						ITypeAnnotationWalker methodWalker = ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER;
 						if (sourceLevel < ClassFileConstants.JDK1_8)
 							methodWalker = binaryType.enrichWithExternalAnnotationsFor(methodWalker, iMethods[i], this.environment);
@@ -984,16 +984,78 @@
 	return result;
 }
 
-private VariableBinding[] createFields(IBinaryField[] iFields, IBinaryType binaryType, long sourceLevel, char[][][] missingTypeNames, boolean isComponent) {
+private abstract static class VariableBindingInitialization<X extends VariableBinding> {
+	abstract void setEmptyResult(BinaryTypeBinding self);
+	abstract X createBinding(BinaryTypeBinding self, IBinaryField binaryField, TypeBinding type);
+	abstract X[] createResultArray(int size);
+	abstract void set(BinaryTypeBinding self, X[] result);
+}
+
+private final static VariableBindingInitialization<FieldBinding> FIELD_INITIALIZATION = new VariableBindingInitialization<FieldBinding>() {
+
+	@Override
+	void setEmptyResult(BinaryTypeBinding self) {
+		set(self, Binding.NO_FIELDS);
+	}
+
+	@Override
+	FieldBinding createBinding(BinaryTypeBinding self, IBinaryField binaryField, TypeBinding type) {
+		return new FieldBinding(
+				binaryField.getName(),
+				type,
+				binaryField.getModifiers() | ExtraCompilerModifiers.AccUnresolved,
+				self,
+				binaryField.getConstant());
+	}
+
+	@Override
+	FieldBinding[] createResultArray(int size) {
+		return new FieldBinding[size];
+	}
+
+	@Override
+	void set(BinaryTypeBinding self, FieldBinding[] result) {
+		self.fields = result;
+	}
+};
+
+private final static VariableBindingInitialization<RecordComponentBinding> RECORD_INITIALIZATION = new VariableBindingInitialization<RecordComponentBinding>() {
+
+	@Override
+	void setEmptyResult(BinaryTypeBinding self) {
+		set(self, Binding.NO_COMPONENTS);
+	}
+
+	@Override
+	RecordComponentBinding createBinding(BinaryTypeBinding self, IBinaryField binaryField, TypeBinding type) {
+		return new RecordComponentBinding(
+				binaryField.getName(),
+				type,
+				binaryField.getModifiers() | ExtraCompilerModifiers.AccUnresolved,
+				self);
+	}
+
+	@Override
+	RecordComponentBinding[] createResultArray(int size) {
+		return new RecordComponentBinding[size];
+	}
+
+	@Override
+	void set(BinaryTypeBinding self, RecordComponentBinding[] result) {
+		self.components = result;
+	}
+};
+
+private void createFields(IBinaryField[] iFields, IBinaryType binaryType, long sourceLevel, char[][][] missingTypeNames, VariableBindingInitialization initialization) {
 	if (!isPrototype()) throw new IllegalStateException();
 	boolean save = this.environment.mayTolerateMissingType;
 	this.environment.mayTolerateMissingType = true;
-	VariableBinding[] tFields = isComponent ? Binding.NO_COMPONENTS : Binding.NO_FIELDS;
+	boolean inited = false;
 	try {
 		if (iFields != null) {
 			int size = iFields.length;
 			if (size > 0) {
-				VariableBinding[] fields1 = isComponent ? new RecordComponentBinding[size] : new FieldBinding[size];
+				VariableBinding[] fields1 = initialization.createResultArray(size);
 				boolean use15specifics = sourceLevel >= ClassFileConstants.JDK1_5;
 				boolean hasRestrictedAccess = hasRestrictedAccess();
 				int firstAnnotatedFieldIndex = -1;
@@ -1009,19 +1071,7 @@
 					TypeBinding type = fieldSignature == null
 						? this.environment.getTypeFromSignature(binaryField.getTypeName(), 0, -1, false, this, missingTypeNames, walker)
 						: this.environment.getTypeFromTypeSignature(new SignatureWrapper(fieldSignature), Binding.NO_TYPE_VARIABLES, this, missingTypeNames, walker);
-					VariableBinding field =
-							isComponent ?
-									new RecordComponentBinding(
-										binaryField.getName(),
-										type,
-										binaryField.getModifiers() | ExtraCompilerModifiers.AccUnresolved,
-										this) :
-									new FieldBinding(
-										binaryField.getName(),
-										type,
-										binaryField.getModifiers() | ExtraCompilerModifiers.AccUnresolved,
-										this,
-										binaryField.getConstant());
+					VariableBinding field = initialization.createBinding(this, binaryField, type);
 					if (declAnnotations != null) {
 						for (IBinaryAnnotation annotation : declAnnotations) {
 							char[] typeName = annotation.getTypeName();
@@ -1068,20 +1118,23 @@
 					}
 // SH}
 				}
-				tFields = fields1;
+				initialization.set(this, fields1);
+				inited = true;
 				// second pass for reifying annotations, since may refer to fields being constructed (147875)
 				if (firstAnnotatedFieldIndex >= 0) {
 					for (int i = firstAnnotatedFieldIndex; i <size; i++) {
 						IBinaryField binaryField = iFields[i];
-						tFields[i].setAnnotations(createAnnotations(binaryField.getAnnotations(), this.environment, missingTypeNames), false);
+						fields1[i].setAnnotations(createAnnotations(binaryField.getAnnotations(), this.environment, missingTypeNames), false);
 					}
 				}
 			}
 		}
 	} finally {
 		this.environment.mayTolerateMissingType = save;
+		if (!inited) {
+			initialization.setEmptyResult(this);
+		}
 	}
-	return tFields;
 }
 //{ObjectTeams: some fields are indeed value parameters:
 private SyntheticArgumentBinding[] valueParameters = NO_SYNTH_ARGUMENTS;
@@ -1808,6 +1861,15 @@
 	FieldBinding field = ReferenceBinding.binarySearch(fieldName, this.fields);
 	return needResolve && field != null ? resolveTypeFor(field) : field;
 }
+
+/**
+ * @return true, when the fields (or in the case of record, the record components) are fully initialized.
+ */
+@Override
+protected boolean isFieldInitializationFinished() {
+	return this.fields != null || this.components != null;
+}
+
 /**
  *  Rewrite of default memberTypes() to avoid resolving eagerly all member types when one is requested
  */
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
index de8d359..52eff80 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2020 IBM Corporation and others.
+ * Copyright (c) 2005, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -49,6 +49,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.lookup;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Set;
@@ -1156,6 +1157,16 @@
 	}
 
 	@Override
+	public ReferenceBinding[] permittedTypes() {
+		ReferenceBinding[] permTypes = this.type.permittedTypes();
+		List<ReferenceBinding> applicablePermTypes = new ArrayList<>();
+		for (ReferenceBinding pt : permTypes) {
+			if (pt.isCompatibleWith(this))
+				applicablePermTypes.add(pt);
+		}
+		return applicablePermTypes.toArray(new ReferenceBinding[0]);
+	}
+	@Override
 	public TypeBinding unannotated() {
 		return this.hasTypeAnnotations() ? this.environment.getUnannotatedType(this) : this;
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
index da8026d..64ddd1e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
@@ -449,6 +449,12 @@
 	return;
 }
 
+/**
+ * @return true, if the fields of the binding are fully initialized.
+ */
+protected boolean isFieldInitializationFinished() {
+	return true;
+}
 
 /**
  * Answer true if the receiver can be instantiated
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java
index 1c38a0b..72e886e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java
@@ -14,8 +14,16 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.parser;
 
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameEOF;
+
+import java.io.IOException;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.compiler.InvalidInputException;
@@ -86,6 +94,9 @@
 	protected int kind;
 	protected int tagValue = NO_TAG_VALUE;
 	protected int lastBlockTagValue = NO_TAG_VALUE;
+	protected boolean snippetInlineTagStarted = false;
+	private int nonRegionTagCount, inlineTagCount;
+	final static String SINGLE_LINE_COMMENT = "//"; //$NON-NLS-1$
 
 	// Line pointers
 	private int linePtr, lastLinePtr;
@@ -112,6 +123,9 @@
 	protected int providesReferencesPtr = -1;
 	protected TypeReference[] providesReferencesStack;
 
+	// Snippet search project path as src classpath for file/class support
+	private String projectPath;
+	private List srcClasspath;
 
 	protected AbstractCommentParser(Parser sourceParser) {
 		this.sourceParser = sourceParser;
@@ -245,7 +259,7 @@
 								this.inlineTagStarted = false;
 								openingBraces = 0;
 							}
-						} else if ((!this.lineStarted || previousChar == '{')) {
+						} else if ((!this.lineStarted || previousChar == '{') || lookForTagsInSnippets()) {
 							if (this.inlineTagStarted) {
 								setInlineTagStarted(false);
 								// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=53279
@@ -271,6 +285,7 @@
 								setInlineTagStarted(true);
 								invalidInlineTagLineEnd = this.lineEnd;
 							} else if (this.textStart != -1 && this.textStart < invalidTagLineEnd) {
+								if(!lookForTagsInSnippets())
 								pushText(this.textStart, invalidTagLineEnd);
 							}
 							this.scanner.resetTo(this.index, this.javadocEnd);
@@ -536,6 +551,13 @@
 	 * Parse argument in @see tag method reference
 	 */
 	protected Object parseArguments(Object receiver) throws InvalidInputException {
+		return parseArguments(receiver, true);
+	}
+
+	/*
+	 * Parse argument in @see tag method reference
+	 */
+	protected Object parseArguments(Object receiver, boolean checkVerifySpaceOrEndComment) throws InvalidInputException {
 
 		// Init
 		int modulo = 0; // should be 2 for (Type,Type,...) or 3 for (Type arg,Type arg,...)
@@ -651,7 +673,7 @@
 					iToken++;
 				} else if (token == TerminalTokens.TokenNameRPAREN) {
 					// verify characters after arguments declaration (expecting white space or end comment)
-					if (!verifySpaceOrEndComment()) {
+					if (checkVerifySpaceOrEndComment && !verifySpaceOrEndComment()) {
 						int end = this.starPosition == -1 ? this.lineEnd : this.starPosition;
 						if (this.source[end]=='\n') end--;
 						if (this.reportProblems) this.sourceParser.problemReporter().javadocMalformedSeeReference(start, end);
@@ -696,6 +718,10 @@
 		return false;
 	}
 
+	protected boolean lookForTagsInSnippets() {
+		return false;
+	}
+
 	/*
 	 * Parse an URL link reference in @see tag
 	 */
@@ -807,10 +833,14 @@
 		return false;
 	}
 
+	protected Object parseMember(Object receiver) throws InvalidInputException {
+		return parseMember(receiver, false);
+	}
+
 	/*
 	 * Parse a method reference in @see tag
 	 */
-	protected Object parseMember(Object receiver) throws InvalidInputException {
+	protected Object parseMember(Object receiver, boolean refInStringLiteral) throws InvalidInputException {
 		// Init
 		this.identifierPtr = -1;
 		this.identifierLengthPtr = -1;
@@ -830,19 +860,27 @@
 			try {
 				// Look for next token to know whether it's a field or method reference
 				int previousPosition = this.index;
-				if (readToken() == TerminalTokens.TokenNameLPAREN) {
-					consumeToken();
-					start = this.scanner.getCurrentTokenStartPosition();
-					try {
-						return parseArguments(receiver);
-					} catch (InvalidInputException e) {
-						int end = this.scanner.getCurrentTokenEndPosition() < this.lineEnd ?
-								this.scanner.getCurrentTokenEndPosition() :
-								this.scanner.getCurrentTokenStartPosition();
-						end = end < this.lineEnd ? end : this.lineEnd;
-						if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidSeeReferenceArgs(start, end);
+				try {
+					int token = readToken();
+					if (token == TerminalTokens.TokenNameLPAREN) {
+						consumeToken();
+						start = this.scanner.getCurrentTokenStartPosition();
+						try {
+							return parseArguments(receiver, !refInStringLiteral);
+						} catch (InvalidInputException e) {
+							int end = this.scanner.getCurrentTokenEndPosition() < this.lineEnd ?
+									this.scanner.getCurrentTokenEndPosition() :
+									this.scanner.getCurrentTokenStartPosition();
+							end = end < this.lineEnd ? end : this.lineEnd;
+							if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidSeeReferenceArgs(start, end);
+						}
+						return null;
 					}
-					return null;
+				} catch (InvalidInputException e) {
+					if (!refInStringLiteral || (!Scanner.INVALID_CHAR_IN_STRING.equals(e.getMessage())
+							&& !Scanner.INVALID_CHARACTER_CONSTANT.equals(e.getMessage()))) {
+						throw e;
+					}
 				}
 
 				// Reset position: we want to rescan last token
@@ -851,7 +889,7 @@
 				this.currentTokenType = -1;
 
 				// Verify character(s) after identifier (expecting space or end comment)
-				if (!verifySpaceOrEndComment()) {
+				if (!refInStringLiteral && !verifySpaceOrEndComment()) {
 					int end = this.starPosition == -1 ? this.lineEnd : this.starPosition;
 					if (this.source[end]=='\n') end--;
 					if (this.reportProblems) this.sourceParser.problemReporter().javadocMalformedSeeReference(start, end);
@@ -1467,6 +1505,1215 @@
 		return false;
 	}
 
+	protected boolean parseSnippet() throws InvalidInputException {
+		boolean tokenWhiteSpace = this.scanner.tokenizeWhiteSpace;
+		boolean tokenizeComments = this.scanner.tokenizeComments;
+		this.scanner.tokenizeWhiteSpace = true;
+		this.scanner.tokenizeComments = true;
+		int previousPosition = -1;
+		int lastRBracePosition = -1;
+		int openBraces = 1;
+		boolean parsingJava18Plus = this.scanner != null ? this.scanner.sourceLevel >= ClassFileConstants.JDK18 : false;
+		boolean valid = true;
+		if (!parsingJava18Plus) {
+			throw new InvalidInputException();
+		}
+		Object snippetTag = null;
+		this.nonRegionTagCount = 0;
+		this.inlineTagCount = 0;
+		try {
+			snippetTag = createSnippetTag();
+			Map<String, String> snippetAttributes  = new HashMap();
+			if (!parseTillColon(snippetAttributes)) {
+				int token = readTokenSafely();
+				boolean eitherNameorClass = token == TerminalTokens.TokenNameIdentifier || token == TerminalTokens.TokenNameclass ;
+				if (!eitherNameorClass ) {
+					this.setSnippetError(snippetTag, "Missing colon"); //$NON-NLS-1$
+					this.setSnippetIsValid(snippetTag, false);
+					if(this.reportProblems)
+						this.sourceParser.problemReporter().javadocInvalidSnippetMissingColon(this.index, this.lineEnd);
+					valid = false;
+				} else {
+					final String FILE = "file"; //$NON-NLS-1$
+					final String CLASS = "class"; //$NON-NLS-1$
+					consumeToken();
+					valid = false;
+					String snippetType = this.scanner.getCurrentTokenString();
+					switch (snippetType) {
+						case FILE:
+							consumeToken();
+							int start = this.scanner.getCurrentTokenStartPosition();
+							token = readTokenSafely();
+							if (token==TerminalTokens.TokenNameEQUAL) {
+								consumeToken();
+								token = readTokenSafely();
+								String regionName = null;
+								if (token==TerminalTokens.TokenNameERROR||token==TerminalTokens.TokenNameStringLiteral){
+									String fileName = this.scanner.getCurrentTokenString();
+									int lastIndex = fileName.length() - 1;
+									if ((fileName.charAt(0) =='"' && fileName.charAt(lastIndex)=='"')
+											||(fileName.charAt(0) =='\'' && fileName.charAt(lastIndex)=='\'')) {
+										fileName = fileName.substring(1, lastIndex); // strip out quotes
+										Path filePath = getFilePathFromFileName(fileName);
+										try {
+											valid = filePath==null ? false : readFileWithRegions(start, regionName, filePath);
+										} catch (IOException e) {
+											valid = false;
+											this.setSnippetError(snippetTag, "Error in reading file"); //$NON-NLS-1$
+										}
+									}
+								}
+							}
+							if (snippetTag != null) {
+								this.setSnippetIsValid(snippetTag, valid);
+							}
+							break;
+						case CLASS:
+							consumeToken();
+							start = this.scanner.getCurrentTokenStartPosition();
+							token = readTokenSafely();
+							if (token==TerminalTokens.TokenNameEQUAL) {
+								consumeToken();
+								token = readTokenSafely();
+								String regionName = null;
+								if (token==TerminalTokens.TokenNameERROR||token==TerminalTokens.TokenNameStringLiteral){
+									String className = this.scanner.getCurrentTokenString();
+									int lastIndex = className.length() - 1;
+									if ((className.charAt(0) =='"' && className.charAt(lastIndex)=='"')
+											||(className.charAt(0) =='\'' && className.charAt(lastIndex)=='\'')) {
+										className = className.substring(1, lastIndex); // strip out quotes
+										if(className.contains(".")) { //$NON-NLS-1$
+											className = className.replace('.', '/');
+										}
+										String fileName = className+".java";//$NON-NLS-1$
+										Path filePath = getFilePathFromFileName(fileName);
+
+										try {
+											valid = filePath==null ? false : readFileWithRegions(start, regionName, filePath);
+										} catch (IOException e) {
+											valid = false;
+											this.setSnippetError(snippetTag, "Error in reading class"); //$NON-NLS-1$
+										}
+									}
+								}
+							}
+							if (snippetTag != null) {
+								this.setSnippetIsValid(snippetTag, valid);
+							}
+							break;
+						default:
+							valid = false;
+					}
+				}
+			} else {
+				if (this.index < this.scanner.eofPosition) {
+					int token = readTokenSafely();
+					if (token == TerminalTokens.TokenNameWHITESPACE) {
+						if (containsNewLine(this.scanner.getCurrentTokenString())) {
+							consumeToken();
+						} else {
+							valid = false;
+							if(this.reportProblems) {
+								//after colon new line required
+								this.sourceParser.problemReporter().javadocInvalidSnippetContentNewLine(this.index, this.lineEnd);
+							}
+							this.setSnippetIsValid(snippetTag, false);
+							this.setSnippetError(snippetTag, "Snippet content should be in a new line"); //$NON-NLS-1$
+
+						}
+					}
+				} else {
+					//when will this happen?? never?
+					valid = false;
+				}
+			}
+			if(hasID(snippetAttributes)) {
+				this.setSnippetID(snippetTag, getID(snippetAttributes));
+			}
+			int textEndPosition = this.index;
+			this.textStart = this.index;
+			int token;
+			while (this.index < this.scanner.eofPosition) {
+				this.index = this.scanner.currentPosition;
+				if (openBraces == 0) {
+					break;
+				}
+				previousPosition = this.index;
+				token = readTokenSafely();
+				if (token == TerminalTokens.TokenNameEOF) {
+					break;
+				}
+				switch (token) {
+					case TerminalTokens.TokenNameLBRACE:
+						openBraces++;
+						textEndPosition = this.index;
+						break;
+					case TerminalTokens.TokenNameRBRACE:
+						openBraces--;
+						textEndPosition = this.index;
+						lastRBracePosition = this.scanner.currentPosition;
+						if (openBraces == 0) {
+							if (this.lineStarted) {
+								if (this.textStart == -1) {
+									this.textStart = previousPosition;
+								}
+								if (this.textStart != -1 && this.textStart < this.index) {
+									String textToBeAdded= new String( this.source, this.textStart, this.index-this.textStart);
+									int iindex = textToBeAdded.indexOf('*');
+									if (iindex > -1 && textToBeAdded.substring(0, iindex+1).trim().equals("*")) { //$NON-NLS-1$
+										textToBeAdded = textToBeAdded.substring(iindex+1);
+									}
+									if (!textToBeAdded.isBlank()) {
+										pushSnippetText(this.textStart, this.index-1, false, snippetTag);
+										this.nonRegionTagCount = 0;
+										this.inlineTagCount = 0;
+									}
+								}
+							}
+						}
+						break;
+					case TerminalTokens.TokenNameWHITESPACE:
+						if (containsNewLine(this.scanner.getCurrentTokenString())) {
+							if (this.lineStarted) {
+								if (this.textStart != -1 && this.textStart < textEndPosition) {
+									if (isProperties(snippetAttributes)) { //single quotes
+										String str = new String(this.source, this.textStart,
+												textEndPosition - this.textStart);
+										if (str.length() > 0 && (str.charAt(0) == '*' ||  str.charAt(0) == '#' ))  {
+											if(str.charAt(0) == '*' )
+												str = str.substring(1);
+											str = str.stripLeading().stripTrailing();
+											if (str.length() > 0 && str.charAt(0) == '#'
+													&& str.charAt(str.length() - 1) == ':') {
+												str = SINGLE_LINE_COMMENT + str.substring(1, str.length() - 1);
+												Object innerTag = parseSnippetInlineTags(str, snippetTag);
+												if (innerTag != null) {
+													addSnippetInnerTag(innerTag, snippetTag);
+													this.snippetInlineTagStarted = true;
+													this.lineStarted = false;
+													this.textStart = -1;
+													break;
+												}
+											}
+										}
+									}
+									pushSnippetText(this.textStart, textEndPosition, true, snippetTag);
+									this.nonRegionTagCount = 0;
+									this.inlineTagCount = 0;
+								}
+							}
+							this.lineStarted = false;
+							// Fix bug 51650
+							this.textStart = -1;
+						}
+						break;
+					case TerminalTokens.TokenNameCOMMENT_LINE:
+						String tokenString = this.scanner.getCurrentTokenString();
+						boolean handleNow = handleCommentLineForCurrentLine(tokenString);
+						boolean lvalid = false;
+						int indexOfLastComment = -1;
+						int noSingleLineComm = getNumberOfSingleLineCommentInSnippetTag(tokenString.substring(2));
+						if (noSingleLineComm > 0)
+							indexOfLastComment = indexOfLastSingleComment(tokenString.substring(2),noSingleLineComm);
+						if (!handleNow) {
+							this.nonRegionTagCount = 0;
+							this.inlineTagCount = 0;
+						}
+						Object innerTag = parseSnippetInlineTags(indexOfLastComment == -1 ? tokenString : tokenString.substring(indexOfLastComment+2), snippetTag);
+						if (innerTag != null) {
+							lvalid = true;
+						}
+						if( lvalid && handleNow && innerTag != snippetTag) {
+							if ( innerTag != snippetTag )
+								addSnippetInnerTag(innerTag, snippetTag);
+							this.snippetInlineTagStarted = true;
+						}
+						textEndPosition = this.index;
+						int textPos = previousPosition;
+						if (!lvalid) {
+							textPos = textEndPosition;
+						}
+						if (this.lineStarted) {
+							if (this.textStart == -1) {
+								this.textStart = previousPosition;
+							}
+							if (this.textStart != -1 && this.textStart < this.index) {
+								pushSnippetText(this.textStart,(innerTag!=null &&  indexOfLastComment >=0) ? textPos+indexOfLastComment+2:textPos, lvalid, snippetTag);
+								if (handleNow) {
+									this.nonRegionTagCount = 0;
+									this.inlineTagCount = 0;
+								}
+							}
+						}
+						if (lvalid && !handleNow) {
+							if ( innerTag != snippetTag )
+								addSnippetInnerTag(innerTag, snippetTag);
+							this.snippetInlineTagStarted = true;
+						}
+						//valid = valid & lvalid;
+						break;
+					default:
+						if (!this.lineStarted || this.textStart == -1) {
+							this.textStart = previousPosition;
+						}
+						this.lineStarted = true;
+						textEndPosition = this.index;
+						break;
+				}
+				consumeToken();
+			}
+		}
+		finally {
+			if(!areRegionsClosed()) {
+				if(this.reportProblems) {
+					this.sourceParser.problemReporter().javadocInvalidSnippetRegionNotClosed(this.index, this.lineEnd);
+				}
+				this.setSnippetError(snippetTag, "Region not closed"); //$NON-NLS-1$
+				this.setSnippetIsValid(snippetTag, false);
+			}
+			// we have to make sure that this is reset to the previous value even if an exception occurs
+			this.scanner.tokenizeWhiteSpace = tokenWhiteSpace;
+			this.scanner.tokenizeComments = tokenizeComments;
+		}
+		boolean retVal = false;
+		if (!valid) {
+			retVal =  false;
+		} else if (openBraces == 0) {
+			this.scanner.currentPosition = lastRBracePosition-1;
+			this.index = lastRBracePosition-1;
+			retVal = true;
+		}
+		if (retVal == false && openBraces == 0) {
+			this.scanner.currentPosition = lastRBracePosition - 1;
+			this.index = lastRBracePosition - 1;
+		}
+		if (snippetTag != null) {
+			this.setSnippetIsValid(snippetTag, retVal);
+		}
+		return retVal;
+	}
+
+	private Path getFilePathFromFileName(String fileName) {
+		if(this.projectPath == null)
+			return null;
+		ArrayList<String> sourceClassPaths = (ArrayList<String>) this.srcClasspath;
+		Path filePath = null;
+		for (String iPath : sourceClassPaths) {
+			filePath = FileSystems.getDefault().getPath(this.projectPath, iPath, fileName);
+			if(filePath.toFile().exists())
+				break;
+		}
+		return filePath;
+	}
+
+	private boolean readFileWithRegions(int start, String regionName, Path filePath) throws IOException {
+		boolean valid = false;
+		int token;
+		int lastIndex;
+		String contents = Files.readString(filePath);
+		int end = this.scanner.getCurrentTokenEndPosition();
+		consumeToken();
+		boolean foundRegionDef = false;
+		final String REGION = "region"; //$NON-NLS-1$
+		while (this.index<this.scanner.eofPosition) {
+			token = readTokenSafely();
+			if (token == TerminalTokens.TokenNameRBRACE) {
+				end = this.index;
+				valid = true;
+				break;
+			} else if (token == TerminalTokens.TokenNameIdentifier) {
+				consumeToken();
+				if (this.scanner.getCurrentTokenString().equals(REGION)) {
+					foundRegionDef = true;
+					break;
+				}
+			} else {
+				consumeToken();
+			}
+		}
+
+		if (foundRegionDef) {
+			token = readTokenSafely();
+			if (token!= TerminalTokens.TokenNameEQUAL) {
+				valid = false;
+			}
+			consumeToken();
+			token = readTokenSafely();
+			if (token==TerminalTokens.TokenNameERROR||token==TerminalTokens.TokenNameStringLiteral){
+				regionName = this.scanner.getCurrentTokenString();
+				consumeToken();
+				lastIndex = regionName.length() - 1;
+				if ((regionName.charAt(0) =='"' && regionName.charAt(lastIndex)=='"')
+						||(regionName.charAt(0) =='\'' && regionName.charAt(lastIndex)=='\'')) {
+					regionName = regionName.substring(1, lastIndex); // strip out quotes
+					end = this.scanner.getCurrentTokenEndPosition();
+				}
+				while (this.index<this.scanner.eofPosition) {
+					token = readTokenSafely();
+					if (token == TerminalTokens.TokenNameRBRACE) {
+						end = this.index;
+						valid = true;
+						break;
+					} else {
+						consumeToken();
+					}
+				}
+			}
+		}
+
+		if (valid) {
+			String snippetText = extractSnippet(contents, regionName);
+			pushExternalSnippetText(snippetText, start, end);
+			this.index = end;
+			this.scanner.currentPosition = end;
+		}
+		return valid;
+	}
+
+	private boolean isProperties(Map<String, String> snippetAttributes) {
+		if (snippetAttributes.size()==0)
+			return false;
+		for (Map.Entry<String, String> entry : snippetAttributes.entrySet()) {
+		    String key = entry.getKey();
+		    String value = entry.getValue();
+		    if(key.equals("lang") && value.equals("properties")) { //$NON-NLS-1$ //$NON-NLS-2$
+		    	return true;
+		    }
+		}
+		return false;
+	}
+
+	private boolean hasID(Map<String, String> snippetAttributes) {
+		if (snippetAttributes.size()==0)
+			return false;
+		for (String key: snippetAttributes.keySet()) {
+			   if(key.equals("id")) { //$NON-NLS-1$
+			    	return true;
+			    }
+		}
+		return false;
+	}
+	private String getID(Map<String, String> snippetAttributes) {
+		for (Map.Entry<String, String> entry : snippetAttributes.entrySet()) {
+		    String key = entry.getKey();
+		    String value = entry.getValue();
+		    if(key.equals("id") ) { //$NON-NLS-1$
+		    	return value;
+		    }
+		}
+		return ""; //$NON-NLS-1$
+	}
+
+	private String extractSnippet(String contents, String region) {
+		String snippetString = ""; //$NON-NLS-1$
+		final String START  = "start"; //$NON-NLS-1$
+		final String END    = "end"; //$NON-NLS-1$
+		final String REGION = "region"; //$NON-NLS-1$
+		int regionLen = REGION.length();
+		boolean extractRegion = region == null? false:true; // false if we don't have a region to extract
+		boolean insideRegion = false;
+		boolean containsJavadocsnippetTags = false;
+		Scanner snippetScanner = new Scanner(true, true, false, this.scanner.sourceLevel, this.scanner.complianceLevel,
+				null, null, false, false);
+		snippetScanner.setSource(contents.toCharArray());
+		while (true) {
+			int tokenType = 0;
+			try {
+				tokenType = snippetScanner.getNextToken();
+				containsJavadocsnippetTags = false;
+				if (tokenType == TokenNameEOF)
+					break;
+				if (tokenType == TerminalTokens.TokenNameCOMMENT_LINE) {
+					String commentLine = snippetScanner.getCurrentTokenString();
+					int regionIndex = commentLine.indexOf(REGION);
+					if (commentLine.contains("@"+START)) { //$NON-NLS-1$
+						if (regionIndex != -1) {
+							int regionNameStart = regionIndex + regionLen + 1;
+							char namedelim = commentLine.charAt(regionNameStart);
+							int regionNameEnd = commentLine.indexOf(namedelim, regionNameStart +1);
+							String regionName = commentLine.substring(regionNameStart +1, regionNameEnd);
+							if (regionName.equals(region)) {
+								insideRegion = true;
+							}
+						}
+					}
+					if (commentLine.contains("@"+END)) { //$NON-NLS-1$
+						if (regionIndex != -1) {
+							int regionNameStart = regionIndex + regionLen + 1;
+							char namedelim = commentLine.charAt(regionNameStart);
+							int regionNameEnd = commentLine.indexOf(namedelim, regionNameStart +1);
+							String regionName = commentLine.substring(regionNameStart +1, regionNameEnd);
+							if (regionName.equals(region)) {
+								insideRegion = false;
+							}
+						} else {
+							insideRegion = false;
+						}
+					}
+					if (insideRegion) {
+					int javadocSnippetTagStart = commentLine.lastIndexOf("//"); //$NON-NLS-1$
+						if (javadocSnippetTagStart >= 0 ) {
+							if (commentLine.substring(javadocSnippetTagStart + 2).stripLeading().startsWith("@")) { //$NON-NLS-1$
+								containsJavadocsnippetTags = true;
+								snippetString = snippetString + commentLine.substring(0, javadocSnippetTagStart) + System.lineSeparator();
+							}
+						}
+					}
+				}
+				if ((!extractRegion||insideRegion)&&(!containsJavadocsnippetTags)) {
+					snippetString = snippetString + snippetScanner.getCurrentTokenString();
+				}
+			} catch (InvalidInputException e) {
+				e.printStackTrace();
+			}
+
+		}
+		return snippetString;
+	}
+
+
+	private boolean parseTillColon(Map<String, String> snippetAttributes) {
+		boolean isValid =  true;
+		boolean colonTokenFound = false;
+		int token;
+		String key = null;
+		boolean lookForValue = false;
+		while (this.index < this.scanner.eofPosition) {
+			token = readTokenSafely();
+			switch(token) {
+				case TerminalTokens.TokenNameWHITESPACE :
+					if (containsNewLine(this.scanner.getCurrentTokenString())) {
+						consumeToken();
+						if (this.index < this.scanner.eofPosition) {
+							token = readTokenSafely();
+							if (token == TerminalTokens.TokenNameMULTIPLY) {
+								consumeToken();
+							} else {
+								isValid = false;
+							}
+						} else {
+							isValid = false;
+						}
+					} else {
+						consumeToken();
+					}
+					break;
+				case TerminalTokens.TokenNameCOLON :
+					consumeToken();
+					colonTokenFound = true;
+					break;
+				case TerminalTokens.TokenNameclass:
+					if(lookForValue == false) {
+						isValid = false;
+					}
+					break;
+
+				case TerminalTokens.TokenNameStringLiteral:
+				case TerminalTokens.TokenNameIdentifier: // name and equal can come for attribute
+					String isFile = this.scanner.getCurrentTokenString();
+					if(isFile.equals("file") && lookForValue == false) { //$NON-NLS-1$
+						isValid = false;
+						break;
+					}
+					consumeToken();
+					if (key == null)
+						key = this.scanner.getCurrentTokenString();
+					if (lookForValue && key != null) {
+						String value = this.scanner.getCurrentTokenString();
+						snippetAttributes.put(key,
+								token == TerminalTokens.TokenNameStringLiteral ? value.substring(1, value.length() - 1)
+										: value);
+						lookForValue = false;
+						key = null;
+					}
+
+				 	break;
+				case TerminalTokens.TokenNameEQUAL :
+					consumeToken();
+					lookForValue=true;
+					break;
+				case TerminalTokens.TokenNameERROR:
+					String currentTokenString = this.scanner.getCurrentTokenString();
+					if(currentTokenString.length()> 1 && currentTokenString.charAt(0) =='\'' && currentTokenString.charAt(currentTokenString.length()-1) =='\'') {
+						if (lookForValue && key != null) {
+							String value = this.scanner.getCurrentTokenString();
+							snippetAttributes.put(key, value.substring(1, value.length() - 1));
+							lookForValue = false;
+							key = null;
+							break;
+						}
+					}
+					if (this.scanner.currentCharacter == '"') {
+						if (!lookForValue)
+							isValid = false;
+					}
+					consumeToken();
+
+					break;
+
+				default :
+					isValid = false;
+					break;
+			}
+			if (colonTokenFound || !isValid) {
+				break;
+			}
+		}
+		if (colonTokenFound) {
+			isValid = true;
+		}
+		return isValid;
+	}
+
+
+	public int indexOfLastSingleComment(String tokenString, int last) {
+		int indexOfLastCom = 0;
+		int temp = -1;
+		String tempString = tokenString;
+		for (int i = 0; i < last; ++i) {
+			temp = tempString.indexOf(SINGLE_LINE_COMMENT);
+			if (temp == -1) {
+				indexOfLastCom = 0;
+				break;
+			}
+			tempString = tempString.substring(++temp);
+			indexOfLastCom += temp;
+		}
+		return --indexOfLastCom;
+	}
+
+
+	private boolean handleCommentLineForCurrentLine(String tokenString) {
+		boolean handle = true;
+		if (tokenString != null) {
+			String processed= tokenString.trim();
+			if (processed.endsWith(":")) { //$NON-NLS-1$
+				handle = false;
+			}
+		}
+		return handle;
+	}
+
+
+	protected int getNumberOfSingleLineCommentInSnippetTag(String tokenString) {
+		if (tokenString != null) {
+			String tokenStringStripped = tokenString.stripLeading();
+			Scanner slScanner = new JavadocScanner(true, true, false/* nls */, this.scanner.sourceLevel,
+					this.scanner.complianceLevel, null/* taskTags */, null/* taskPriorities */,
+					false/* taskCaseSensitive */, false, true, true);
+			slScanner.setSource(tokenStringStripped.toCharArray());
+			while (true) {
+				try {
+					int tokenType = slScanner.getNextToken();
+					if (tokenType == TokenNameEOF)
+						break;
+					switch (tokenType) {
+						case TerminalTokens.TokenNameCOMMENT_LINE:
+							return 1 + getNumberOfSingleLineCommentInSnippetTag(tokenStringStripped
+									.substring(2 + tokenStringStripped.indexOf(SINGLE_LINE_COMMENT)));
+					}
+				} catch (InvalidInputException e) {
+					// do nothing
+				}
+			}
+		}
+		return 0;
+	}
+
+	protected Object parseSnippetInlineTags(String tokenString, Object snippetTag) {
+		int commentStart = this.scanner.getCurrentTokenStartPosition();
+		Object inlineTag = null;
+		final String REPLACE = "replace"; //$NON-NLS-1$
+		final String HIGHLIGHT = "highlight"; //$NON-NLS-1$
+		final String SUBSTRING = "substring"; //$NON-NLS-1$
+		final String REGEX = "regex"; //$NON-NLS-1$
+		final String TYPE = "type"; //$NON-NLS-1$
+		final String REPLACEMENT = "replacement"; //$NON-NLS-1$
+		final String REGION = "region"; //$NON-NLS-1$
+		final String END = "end"; //$NON-NLS-1$
+		final String LINK = "link"; //$NON-NLS-1$
+		final String TARGET = "target"; //$NON-NLS-1$
+		boolean regionClosed = false;
+		int initialTagCount = this.nonRegionTagCount;
+		List<Object> inlineTags= new ArrayList<>();
+		try {
+			if (tokenString != null
+					&& tokenString.length() > 2
+					&& tokenString.startsWith(SINGLE_LINE_COMMENT)) {
+				String tobeTokenized = tokenString.substring(2);
+				Scanner slScanner = new JavadocScanner(false, false, false/* nls */, this.scanner.sourceLevel, this.scanner.complianceLevel,
+						null/* taskTags */, null/* taskPriorities */, false/* taskCaseSensitive */, false, true, true);
+				slScanner.setSource(tobeTokenized.toCharArray());
+				boolean atTokenStarted= false;
+				int atTokenPos = -1;
+				boolean firstTagProcessed = false;
+				while (true) {
+					try {
+						int tokenType = slScanner.getNextToken();
+						if (tokenType == TokenNameEOF)
+							break;
+						mainSwitch : switch (tokenType) {
+							case TerminalTokens.TokenNameAT :
+								atTokenStarted = true;
+								atTokenPos = slScanner.getCurrentTokenStartPosition();
+								break;
+							case TerminalTokens.TokenNameIdentifier :
+								if(atTokenStarted==false) //invalid snippet inline, treat it like text
+									return null;
+								if (atTokenStarted) {
+									int curPos= slScanner.getCurrentTokenStartPosition();
+									if (curPos != atTokenPos+1 && !firstTagProcessed) {
+										return inlineTag;
+									}
+									String snippetDecorator = slScanner.getCurrentTokenString();
+									int tokenStart= commentStart + slScanner.getCurrentTokenStartPosition()-1;
+									int tokenEnd= commentStart + slScanner.getCurrentTokenEndPosition();
+									String newTagName= null;
+									switch(snippetDecorator) {
+										case  HIGHLIGHT :
+											tokenStart= commentStart + 1 + slScanner.getCurrentTokenStartPosition();
+											tokenEnd= tokenStart + 10;
+											newTagName = '@' + HIGHLIGHT;
+											Map<String, Object> map = new HashMap<>();
+											boolean breakToMainSwitch = false;
+											boolean createTag = false;
+											String attribute = null;
+											String value = null;
+											boolean processValue = false;
+											boolean createRegion = false;
+											String regionName = null;
+											while (true) {
+												tokenType = slScanner.getNextToken();
+												switch (tokenType) {
+													case TokenNameEOF:
+														createTag = true;
+														break;
+													case TerminalTokens.TokenNameAT:
+														if (!processValue) {
+															breakToMainSwitch = true;
+															createTag = true;
+														}
+														processValue= false;
+														break;
+													case TerminalTokens.TokenNameCOLON:
+														tokenType = slScanner.getNextToken();
+														if (tokenType == TokenNameEOF) {
+															break;
+														} else {
+															return inlineTag;
+														}
+													case TerminalTokens.TokenNameIdentifier:
+														if (processValue) {
+															value = slScanner.getCurrentTokenString();
+															if (map.get(attribute) == null) {
+																map.put(attribute, value);
+																if ((attribute.equals(SUBSTRING) && (map.get(REGEX) != null))
+																		|| (attribute.equals(REGEX) && (map.get(SUBSTRING) != null))) {
+																	reportRegexSubstringTogether(snippetTag);
+																	return inlineTag;
+																}
+															}
+															processValue= false;
+															attribute = null;
+														} else {
+															attribute = slScanner.getCurrentTokenString();
+															switch(attribute) {
+																case  SUBSTRING :
+																case  REGEX :
+																case  TYPE :
+																	break;
+																case  REGION :
+																	createRegion = true;
+																	setRegionPosition(slScanner.currentPosition);
+																	break;
+																default :
+																	break;
+															}
+														}
+														break;
+													case TerminalTokens.TokenNameEQUAL:
+														if (attribute != null) {
+															processValue = true;
+														}
+														break;
+													case TerminalTokens.TokenNameStringLiteral:
+													case TerminalTokens.TokenNameSingleQuoteStringLiteral:
+														if (processValue) {
+															value = slScanner.getCurrentTokenString();
+															value = stripQuotes(value);
+															if (REGION.equals(attribute)) {
+																regionName = value;
+															} else if (map.get(attribute) == null) {
+																map.put(attribute, value);
+																if ((attribute.equals(SUBSTRING) && (map.get(REGEX) != null))
+																		|| (attribute.equals(REGEX) && (map.get(SUBSTRING) != null))) {
+																	reportRegexSubstringTogether(snippetTag);
+																	return inlineTag;
+																}
+															}
+															processValue= false;
+															attribute = null;
+														}
+														break;
+												}
+												if (createTag) {
+													break;
+												}
+												if (breakToMainSwitch)
+													break mainSwitch;
+											}
+											tokenEnd = commentStart + 1 + slScanner.getCurrentTokenEndPosition();
+											inlineTag = createSnippetInnerTag(newTagName, tokenStart, tokenEnd);
+											addTagProperties(inlineTag, map, ++this.inlineTagCount);
+											if (createRegion) {
+												List<Object> tags = new ArrayList<>();
+												tags.add(inlineTag);
+												inlineTag = createSnippetRegion(regionName, tags, snippetTag, false, false);
+											} else {
+												this.nonRegionTagCount++;
+											}
+											inlineTags.add(inlineTag);
+											if (!firstTagProcessed) {
+												firstTagProcessed = true;
+											}
+											break;
+										case REPLACE:
+											tokenStart= commentStart + 1 + slScanner.getCurrentTokenStartPosition();
+											tokenEnd= tokenStart + 8;
+											newTagName = '@' + REPLACE;
+											map = new HashMap<>();
+											breakToMainSwitch = false;
+											createTag = false;
+											attribute = null;
+											value = null;
+											processValue = false;
+											boolean hasReplacementStr = false;
+											createRegion = false;
+											regionName = null;
+											while (true) {
+												tokenType = slScanner.getNextToken();
+												switch (tokenType) {
+													case TokenNameEOF:
+														createTag = true;
+														break;
+													case TerminalTokens.TokenNameAT:
+														if (!processValue) {
+															breakToMainSwitch = true;
+															createTag = true;
+														}
+														processValue= false;
+														break;
+													case TerminalTokens.TokenNameCOLON:
+														tokenType = slScanner.getNextToken();
+														if (tokenType == TokenNameEOF) {
+															break;
+														} else {
+															return inlineTag;
+														}
+													case TerminalTokens.TokenNameIdentifier:
+														if (processValue) {
+															value = slScanner.getCurrentTokenString();
+															if (REGION.equals(attribute)) {
+																regionName = value;
+															} else if (map.get(attribute) == null) {
+																if (attribute.equals(REPLACEMENT)) {
+																	hasReplacementStr = true;
+																}
+																map.put(attribute, value);
+																if ((attribute.equals(SUBSTRING) && (map.get(REGEX) != null))
+																		|| (attribute.equals(REGEX) && (map.get(SUBSTRING) != null))) {
+																	reportRegexSubstringTogether(snippetTag);
+																	return inlineTag;
+																}
+															}
+															processValue= false;
+															attribute = null;
+														} else {
+															attribute = slScanner.getCurrentTokenString();
+															switch(attribute) {
+																case  SUBSTRING :
+																case  REGEX :
+																case  REPLACEMENT :
+																	break;
+																case  REGION :
+																	createRegion = true;
+																	setRegionPosition(slScanner.currentPosition);
+																	break;
+																default :
+																	break;
+															}
+														}
+														break;
+													case TerminalTokens.TokenNameEQUAL:
+														if (attribute != null) {
+															processValue = true;
+														}
+														break;
+													case TerminalTokens.TokenNameStringLiteral:
+													case TerminalTokens.TokenNameSingleQuoteStringLiteral:
+														if (processValue) {
+															value = slScanner.getCurrentTokenString();
+															value = stripQuotes(value);
+															if (REGION.equals(attribute)) {
+																regionName = value;
+															} else if (map.get(attribute) == null) {
+																if (attribute.equals(REPLACEMENT)) {
+																	hasReplacementStr = true;
+																}
+																map.put(attribute, value);
+																if ((attribute.equals(SUBSTRING) && (map.get(REGEX) != null))
+																		|| (attribute.equals(REGEX) && (map.get(SUBSTRING) != null))) {
+																	reportRegexSubstringTogether(snippetTag);
+																	return inlineTag;
+																}
+															}
+															processValue= false;
+															attribute = null;
+														}
+														break;
+												}
+												if (createTag) {
+													break;
+												}
+												if (breakToMainSwitch)
+													break mainSwitch;
+											}
+											if (!hasReplacementStr) {
+												return inlineTag;
+											}
+											tokenEnd = commentStart + 1 + slScanner.getCurrentTokenEndPosition();
+											inlineTag = createSnippetInnerTag(newTagName, tokenStart, tokenEnd);
+											addTagProperties(inlineTag, map, ++this.inlineTagCount);
+											if (createRegion) {
+												List<Object> tags = new ArrayList<>();
+												tags.add(inlineTag);
+												inlineTag = createSnippetRegion(regionName, tags, snippetTag, false, false);
+											} else {
+												this.nonRegionTagCount++;
+											}
+											inlineTags.add(inlineTag);
+											if (!firstTagProcessed) {
+												firstTagProcessed = true;
+											}
+											break;
+										case LINK :
+											tokenStart= commentStart + 1 + slScanner.getCurrentTokenStartPosition();
+											tokenEnd= tokenStart + 4;
+											newTagName = '@' + LINK;
+											map = new HashMap<>();
+											breakToMainSwitch = false;
+											createTag = false;
+											attribute = null;
+											value = null;
+											processValue = false;
+											boolean hasTarget = false;
+											Object type = null;
+											createRegion = false;
+											regionName = null;
+											while (true) {
+												tokenType = slScanner.getNextToken();
+												switch (tokenType) {
+													case TokenNameEOF:
+														createTag = true;
+														break;
+													case TerminalTokens.TokenNameAT:
+														if (!processValue) {
+															breakToMainSwitch = true;
+															createTag = true;
+														}
+														processValue= false;
+														break;
+													case TerminalTokens.TokenNameCOLON:
+														tokenType = slScanner.getNextToken();
+														if (tokenType == TokenNameEOF) {
+															break;
+														} else {
+															return inlineTag;
+														}
+													case TerminalTokens.TokenNameIdentifier:
+														if (processValue) {
+															value = slScanner.getCurrentTokenString();
+															if (map.get(attribute) == null) {
+																if (REGION.equals(attribute)) {
+																	regionName = value;
+																} else if (TARGET.equals(attribute)) {
+																	String originalTokenString = this.scanner.getCurrentTokenString();
+																	int offset = originalTokenString.lastIndexOf(tokenString);
+																	if(offset == -1 ) {
+																		offset = 1- tokenString.length(); // for # converted to // current position at end
+																	}
+																	type = parseLinkReference(slScanner.getCurrentTokenStartPosition() + offset, value);
+																	if (type != null) {
+																		map.put(attribute, type);
+																		hasTarget = true;
+																	}
+																} else {
+																	map.put(attribute, value);
+																	if ((attribute.equals(SUBSTRING) && (map.get(REGEX) != null))
+																			|| (attribute.equals(REGEX) && (map.get(SUBSTRING) != null))) {
+																		reportRegexSubstringTogether(snippetTag);
+																		return inlineTag;
+																	}
+																}
+															}
+															processValue= false;
+															attribute = null;
+														} else {
+															attribute = slScanner.getCurrentTokenString();
+															switch(attribute) {
+																case  SUBSTRING :
+																case  REGEX :
+																case  TYPE :
+																case  TARGET :
+																	break;
+																case  REGION :
+																	createRegion = true;
+																	setRegionPosition(slScanner.currentPosition);
+																	break;
+																default :
+																	break;
+															}
+														}
+														break;
+													case TerminalTokens.TokenNameEQUAL:
+														if (attribute != null) {
+															processValue = true;
+														}
+														break;
+													case TerminalTokens.TokenNameStringLiteral:
+													case TerminalTokens.TokenNameSingleQuoteStringLiteral:
+														if (processValue) {
+															value = slScanner.getCurrentTokenString();
+															if (map.get(attribute) == null) {
+																if (REGION.equals(attribute)) {
+																	value = stripQuotes(value);
+																	regionName = value;
+																} else if (TARGET.equals(attribute)) {
+																	String originalTokenString = this.scanner.getCurrentTokenString();
+																	int offset = originalTokenString.lastIndexOf(tokenString);
+																	if(offset == -1 ) {
+																		offset = 1- tokenString.length(); // for # converted to // current position at end
+																	}
+																	type = parseLinkReference(slScanner.getCurrentTokenStartPosition() + offset, value);
+																	if (type != null) {
+																		map.put(attribute, type);
+																		hasTarget = true;
+																	}
+																} else {
+																	value = stripQuotes(value);
+																	map.put(attribute, value);
+																	if ((attribute.equals(SUBSTRING) && (map.get(REGEX) != null))
+																			|| (attribute.equals(REGEX) && (map.get(SUBSTRING) != null))) {
+																		reportRegexSubstringTogether(snippetTag);
+																		return inlineTag;
+																	}
+																}
+															}
+															processValue= false;
+															attribute = null;
+														}
+														break;
+												}
+												if (createTag) {
+													break;
+												}
+												if (breakToMainSwitch)
+													break mainSwitch;
+											}
+											tokenEnd = commentStart + 1 + slScanner.getCurrentTokenEndPosition();
+											if (hasTarget) {
+												inlineTag = createSnippetInnerTag(newTagName, tokenStart, tokenEnd);
+												addTagProperties(inlineTag, map, ++this.inlineTagCount);
+												if (createRegion) {
+													List<Object> tags = new ArrayList<>();
+													tags.add(inlineTag);
+													inlineTag = createSnippetRegion(regionName, tags, snippetTag, false, false);
+												} else {
+													this.nonRegionTagCount++;
+												}
+												inlineTags.add(inlineTag);
+												if (!firstTagProcessed) {
+													firstTagProcessed = true;
+												}
+											}
+											break;
+										case  END :
+											boolean closeRegion = false;
+											regionName = null;
+											processValue = false;
+											attribute = null;
+											breakToMainSwitch = false;
+											while (true) {
+												tokenType = slScanner.getNextToken();
+												switch (tokenType) {
+													case TokenNameEOF:
+														closeRegion = true;
+														break;
+													case TerminalTokens.TokenNameAT:
+														if (!processValue) {
+															breakToMainSwitch = true;
+															closeRegion = true;
+														}
+														processValue= false;
+														break;
+													case TerminalTokens.TokenNameCOLON:
+														tokenType = slScanner.getNextToken();
+														if (tokenType == TokenNameEOF) {
+															break;
+														} else {
+															return inlineTag;
+														}
+													case TerminalTokens.TokenNameIdentifier:
+														if (processValue && REGION.equals(attribute)) {
+															regionName = slScanner.getCurrentTokenString();
+															processValue= false;
+															attribute = null;
+														} else {
+															attribute = slScanner.getCurrentTokenString();
+															switch(attribute) {
+																case  REGION :
+																	setRegionPosition(slScanner.currentPosition);
+																	break;
+																default :
+																	break;
+															}
+														}
+														break;
+													case TerminalTokens.TokenNameEQUAL:
+														if (attribute != null) {
+															processValue = true;
+														}
+														break;
+													case TerminalTokens.TokenNameStringLiteral:
+													case TerminalTokens.TokenNameSingleQuoteStringLiteral:
+														if (processValue && REGION.equals(attribute)) {
+															regionName = slScanner.getCurrentTokenString();
+															regionName = stripQuotes(regionName);
+														}
+														processValue= false;
+														attribute = null;
+														break;
+												}
+												if (closeRegion) {
+													break;
+												}
+											}
+											if (closeRegion) {
+												tokenEnd = commentStart + 1 + slScanner.getCurrentTokenEndPosition();
+												this.closeJavaDocRegion(regionName, snippetTag, tokenEnd);
+												regionClosed = true;
+												if (!firstTagProcessed) {
+													firstTagProcessed = true;
+												}
+											}
+											if (breakToMainSwitch) {
+												break mainSwitch;
+											}
+											break;
+										default :
+											return inlineTag;
+									}
+								}
+								break;
+							default:
+								return inlineTag;//if at token not started then invalid
+						}
+
+					} catch (InvalidInputException e) {
+						// do nothing
+					}
+				}
+			}
+		}
+		finally {
+			if (inlineTags.size() > 1
+					|| (initialTagCount > 0 && inlineTags.size() > 0)) {
+				inlineTag = createSnippetRegion(null, inlineTags, snippetTag, true, (initialTagCount > 0) ? true : false);
+			} else if (inlineTags.size() == 1) {
+				inlineTag = inlineTags.get(0);
+			}
+		}
+		if (regionClosed && inlineTag == null) {
+			return snippetTag;
+		}
+		return inlineTag;
+	}
+
+	private String stripQuotes(String str) {
+		if (str == null || str.length() <= 2) {
+			return str;
+		}
+		String finalStr= str;
+		int lastIndex = finalStr.length() - 1;
+		if ((finalStr.charAt(0) =='"' && finalStr.charAt(lastIndex)=='"')
+				||(finalStr.charAt(0) =='\'' && finalStr.charAt(lastIndex)=='\'')) {
+			finalStr = finalStr.substring(1, finalStr.length()-1);
+		}
+		return finalStr;
+	}
+	private Object parseLinkReference(int curPosition, String value) {
+		Object typeRef = null;
+		Object reference = null;
+		int indexx = this.index;
+		int oldCurrentPosition = this.scanner.currentPosition;
+		int oldStartPosition = this.scanner.startPosition;
+		char c = value.charAt(0);
+		int additionalIndex = 2;
+		if (c == '"' || c== '\'' ) {
+			additionalIndex += 1;
+		}
+		this.scanner.currentPosition = this.scanner.getCurrentTokenStartPosition() + curPosition  + additionalIndex;
+		int allowedLength = this.scanner.getCurrentTokenStartPosition() + curPosition + value.length();
+		this.index = this.scanner.startPosition;
+		int oldToken = this.currentTokenType;
+		this.currentTokenType = -1;
+		boolean tokenizeWhiteSpaces = this.scanner.tokenizeWhiteSpace;
+		this.scanner.tokenizeWhiteSpace = false;
+		try {
+			while (this.scanner.currentPosition < allowedLength) {
+				int token = readTokenSafely();
+				this.scanner.tokenizeWhiteSpace = true;
+				switch (token) {
+					case TerminalTokens.TokenNameERROR :
+						consumeToken();
+						if (this.scanner.currentCharacter == '#') { // @see ...#member
+							reference = parseMember(typeRef, true);
+						}
+						break;
+					case TerminalTokens.TokenNameIdentifier :
+						typeRef = parseQualifiedName(true, true);
+						break;
+					default :
+						return null;
+				}
+
+			}
+		} catch (InvalidInputException ex) {
+			typeRef= null;
+		}
+		finally {
+			this.scanner.currentPosition = oldCurrentPosition;
+			this.scanner.startPosition = oldStartPosition;
+			this.index = indexx;
+			this.currentTokenType = oldToken;
+			this.scanner.tokenizeWhiteSpace = tokenizeWhiteSpaces;
+		}
+		if (reference != null) {
+			typeRef = reference;
+		}
+		return typeRef;
+	}
+
+	private boolean containsNewLine(String str) {
+		boolean consider = false;
+		if(str != null
+				&& (str.contains(System.lineSeparator())
+						|| str.indexOf('\n') != -1)) {
+			consider = true;
+		}
+		return consider;
+	}
+
 	/*
 	 * Parse tag declaration
 	 */
@@ -1611,11 +2858,49 @@
 		// do not store text by default
 	}
 
+	protected void pushSnippetText(int start, int end, boolean addNewLine, Object snippetTag) {
+		// do not store text by default
+	}
+
+	protected abstract void closeJavaDocRegion(String name, Object snippetTag, int end);
+	protected abstract boolean areRegionsClosed();
+
+	protected void pushExternalSnippetText(String text, int start, int end) {
+		// do not store text by default
+	}
+
+	protected abstract Object createSnippetTag();
+
+	protected abstract Object createSnippetInnerTag(String tagName, int start, int end);
+
+	protected abstract Object createSnippetRegion(String name, List<Object> tags, Object snippetTag, boolean isDummyRegion, boolean considerPrevTag);
+
+	protected abstract void addTagProperties(Object Tag, Map<String, Object> map, int tagCount);
+
+	protected abstract void addSnippetInnerTag(Object tag, Object snippetTag);
+
+	protected abstract void setSnippetError(Object tag, String value);
+
+	protected abstract void setSnippetIsValid(Object tag, boolean value);
+
+	protected abstract void setSnippetID(Object tag, String value);
+
 	/*
 	 * Push a throws type ref in ast node stack.
 	 */
 	protected abstract boolean pushThrowName(Object typeRef);
 
+	protected abstract void setRegionPosition(int currentPosition);
+
+
+	private void reportRegexSubstringTogether(Object snippetTag) {
+		if(this.reportProblems) {
+			this.sourceParser.problemReporter().javadocInvalidSnippetRegexSubstringTogether(this.lineEnd -this.scanner.getCurrentTokenString().length() +2, this.lineEnd);
+		}
+		this.setSnippetIsValid(snippetTag, false);
+		this.setSnippetError(snippetTag, "Regex and substring together"); //$NON-NLS-1$
+	}
+
 	/*
 	 * Read current character and move index position.
 	 * Warning: scanner position is unchanged using this method!
@@ -1957,4 +3242,17 @@
 			this.complianceLevel = this.sourceParser.options.complianceLevel;
 		}
 	}
+
+	/**
+	 * @param projectPath Absolute path in local file system
+	 */
+	public void setProjectPath(String projectPath) {
+		this.projectPath = projectPath;
+	}
+
+	public void setProjectSrcClasspath(List path) {
+		this.srcClasspath = path;
+	}
+
+
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java
index c633cd3..9b48bbf 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java
@@ -14,7 +14,9 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.parser;
 
+import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.compiler.InvalidInputException;
@@ -69,6 +71,9 @@
 	// see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=222900"
 	private int tagWaitingForDescription;
 
+	private ArrayList<String> regionNames = new ArrayList<>();
+	private int regionPosition = -1;
+
 	public JavadocParser(Parser sourceParser) {
 		super(sourceParser);
 		this.kind = COMPIL_PARSER | TEXT_VERIF;
@@ -348,6 +353,66 @@
 	}
 
 	@Override
+	protected Object createSnippetTag() {
+		this.tagValue = TAG_SNIPPET_VALUE;
+		return this.tagValue;
+	}
+
+	@Override
+	protected Object createSnippetRegion(String name, List<Object> tags, Object snippetTag, boolean isDummyRegion, boolean considerPrevTag) {
+		if(this.regionNames.contains(name)) {
+			if(this.reportProblems) {
+				int startPos= this.lineEnd -this.scanner.getCurrentTokenString().length() +2;
+				if(this.regionPosition>0)
+					startPos = startPos+this.regionPosition;
+				this.sourceParser.problemReporter().javadocInvalidSnippetDuplicateRegions(startPos-4, startPos+1);
+			}
+			this.setSnippetIsValid(snippetTag, false);
+			this.setSnippetError(snippetTag, "Duplicate regions"); //$NON-NLS-1$
+		}
+		else {
+			if(name!=null)
+				this.regionNames.add(name);
+		}
+
+		if (tags != null && tags.size() > 0) {
+			return tags.get(0);
+		}
+		return name;
+	}
+
+	@Override
+	protected void setSnippetIsValid(Object obj, boolean value) {
+		//do nothing;
+	}
+
+	@Override
+	protected void setSnippetError(Object obj, String value) {
+		//do nothing;
+	}
+
+	@Override
+	protected void setSnippetID(Object tag, String value) {
+		// do nothing
+
+	}
+
+	@Override
+	protected Object createSnippetInnerTag(String tagName, int start, int end) {
+		return tagName;
+	}
+
+	@Override
+	protected void addTagProperties(Object Tag, Map<String, Object> map, int tagCount) {
+		return;
+	}
+
+	@Override
+	protected void addSnippetInnerTag(Object tag, Object snippetTag) {
+		this.tagValue = TAG_OTHERS_VALUE;
+	}
+
+	@Override
 	protected Object createTypeReference(int primitiveToken) {
 		return createTypeReference(primitiveToken, false);
 	}
@@ -763,6 +828,16 @@
 				} else if (length == TAG_SUMMARY_LENGTH && CharOperation.equals(TAG_SUMMARY, tagName, 0, length)) {
 					this.tagValue = TAG_SUMMARY_VALUE;
 					this.tagWaitingForDescription = this.tagValue;
+				} else if (length == TAG_SNIPPET_LENGTH && CharOperation.equals(TAG_SNIPPET, tagName, 0, length)) {
+					this.tagValue = TAG_SNIPPET_VALUE;
+					this.tagWaitingForDescription = this.tagValue;
+					if (this.inlineTagStarted) {
+						valid = parseSnippet();
+					}
+				}else if (length> TAG_SNIPPET_LENGTH && CharOperation.prefixEquals(TAG_SNIPPET, tagName)) {
+					if (this.reportProblems ) {
+						this.sourceParser.problemReporter().javadocInvalidSnippet(this.tagSourceStart, this.tagSourceEnd);
+					}
 				}
 				break;
 			case 't':
@@ -961,6 +1036,24 @@
 		this.tagWaitingForDescription = NO_TAG_VALUE;
 	}
 
+	@Override
+	protected void  pushSnippetText(int start, int end, boolean addNewLine, Object snippetTag) {
+		// The tag gets its description => clear the flag
+		this.tagWaitingForDescription = TAG_SNIPPET_VALUE;
+	}
+
+	@Override
+	protected void closeJavaDocRegion(String name, Object snippetTag, int end){
+		this.regionNames.remove(name);
+		//do nothing
+	}
+
+	@Override
+	protected void pushExternalSnippetText(String text, int start, int end) {
+		// The tag gets its description => clear the flag
+		this.tagWaitingForDescription = TAG_SNIPPET_VALUE;
+	}
+
 	/*
 	 * Push a throws type ref in ast node stack.
 	 */
@@ -1267,4 +1360,19 @@
 
 	}
 
+
+	@Override
+	/**	 * call at the end of snippet, so clear regionNames
+	 */
+	protected boolean areRegionsClosed() {
+		int size = this.regionNames.size();
+		this.regionNames.clear();
+		return size==0;
+	}
+
+	@Override
+	protected void setRegionPosition(int currentPosition) {
+		this.regionPosition=currentPosition;
+
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocScanner.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocScanner.java
new file mode 100644
index 0000000..cc21b6c
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocScanner.java
@@ -0,0 +1,412 @@
+/*******************************************************************************
+ * Copyright (c) 2022 IBM Corporation 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
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser;
+
+import org.eclipse.jdt.core.compiler.InvalidInputException;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+
+public class JavadocScanner extends Scanner{
+
+	public boolean tokenizeSingleQuotes = false;
+	
+	public boolean considerRegexInStringLiteral = false;
+	
+	public JavadocScanner() {
+		this(false /*comment*/, false /*whitespace*/, false /*nls*/, ClassFileConstants.JDK1_3 /*sourceLevel*/, null/*taskTag*/, null/*taskPriorities*/, true /*taskCaseSensitive*/);
+	}
+
+	public JavadocScanner(
+			boolean tokenizeComments,
+			boolean tokenizeWhiteSpace,
+			boolean checkNonExternalizedStringLiterals,
+			long sourceLevel,
+			long complianceLevel,
+			char[][] taskTags,
+			char[][] taskPriorities,
+			boolean isTaskCaseSensitive,
+			boolean isPreviewEnabled) {
+
+		this(
+				tokenizeComments,
+				tokenizeWhiteSpace,
+				checkNonExternalizedStringLiterals,
+				sourceLevel,
+				complianceLevel,
+				taskTags,
+				taskPriorities,
+				isTaskCaseSensitive,
+				isPreviewEnabled,
+				false,
+				false);
+	}
+
+	public JavadocScanner(
+			boolean tokenizeComments,
+			boolean tokenizeWhiteSpace,
+			boolean checkNonExternalizedStringLiterals,
+			long sourceLevel,
+			char[][] taskTags,
+			char[][] taskPriorities,
+			boolean isTaskCaseSensitive,
+			boolean isPreviewEnabled) {
+
+		this(
+			tokenizeComments,
+			tokenizeWhiteSpace,
+			checkNonExternalizedStringLiterals,
+			sourceLevel,
+			sourceLevel,
+			taskTags,
+			taskPriorities,
+			isTaskCaseSensitive,
+			isPreviewEnabled);
+		
+	}
+
+	public JavadocScanner(
+			boolean tokenizeComments,
+			boolean tokenizeWhiteSpace,
+			boolean checkNonExternalizedStringLiterals,
+			long sourceLevel,
+			char[][] taskTags,
+			char[][] taskPriorities,
+			boolean isTaskCaseSensitive) {
+
+		this(
+			tokenizeComments,
+			tokenizeWhiteSpace,
+			checkNonExternalizedStringLiterals,
+			sourceLevel,
+			sourceLevel,
+			taskTags,
+			taskPriorities,
+			isTaskCaseSensitive,
+			false);
+	}
+	
+	public JavadocScanner(
+			boolean tokenizeComments,
+			boolean tokenizeWhiteSpace,
+			boolean checkNonExternalizedStringLiterals,
+			long sourceLevel,
+			long complianceLevel,
+			char[][] taskTags,
+			char[][] taskPriorities,
+			boolean isTaskCaseSensitive,
+			boolean isPreviewEnabled,
+			boolean tokenizeSingleQuotes,
+			boolean considerRegexInStringLiteral) {
+
+		super(
+				tokenizeComments,
+				tokenizeWhiteSpace,
+				checkNonExternalizedStringLiterals,
+				sourceLevel,
+				complianceLevel,
+				taskTags,
+				taskPriorities,
+				isTaskCaseSensitive,
+				isPreviewEnabled);
+		this.tokenizeSingleQuotes = tokenizeSingleQuotes;
+		this.considerRegexInStringLiteral = considerRegexInStringLiteral;
+	}
+
+	@Override
+	protected int scanForStringLiteral() throws InvalidInputException {
+		if (this.considerRegexInStringLiteral) {
+			this.unicodeAsBackSlash = false;
+			boolean isUnicode = false;
+			try {
+				// consume next character
+				this.unicodeAsBackSlash = false;
+				isUnicode = false;
+				if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+						&& (this.source[this.currentPosition] == 'u')) {
+					getNextUnicodeChar();
+					isUnicode = true;
+				} else {
+					if (this.withoutUnicodePtr != 0) {
+						unicodeStore();
+					}
+				}
+
+				while (this.currentCharacter != '"') {
+					boolean isRegex = false;
+					if (this.currentPosition >= this.eofPosition) {
+						throw new InvalidInputException(UNTERMINATED_STRING);
+					}
+					/**** \r and \n are not valid in string literals ****/
+					if ((this.currentCharacter == '\n') || (this.currentCharacter == '\r')) {
+						// relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
+						if (isUnicode) {
+							int start = this.currentPosition;
+							for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
+								if (this.currentPosition >= this.eofPosition) {
+									this.currentPosition = start;
+									break;
+								}
+								if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
+									isUnicode = true;
+									getNextUnicodeChar();
+								} else {
+									isUnicode = false;
+								}
+								if (!isUnicode && this.currentCharacter == '\n') {
+									this.currentPosition--; // set current position on new line character
+									break;
+								}
+								if (this.currentCharacter == '\"') {
+									throw new InvalidInputException(INVALID_CHAR_IN_STRING);
+								}
+							}
+						} else {
+							this.currentPosition--; // set current position on new line character
+						}
+						throw new InvalidInputException(INVALID_CHAR_IN_STRING);
+					}
+					if (this.currentCharacter == '\\') {
+						if (this.unicodeAsBackSlash) {
+							this.withoutUnicodePtr--;
+							// consume next character
+							this.unicodeAsBackSlash = false;
+							if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
+								getNextUnicodeChar();
+								isUnicode = true;
+								this.withoutUnicodePtr--;
+							} else {
+								isUnicode = false;
+							}
+						} else {
+							if (this.withoutUnicodePtr == 0) {
+								unicodeInitializeBuffer(this.currentPosition - this.startPosition);
+							}
+							this.withoutUnicodePtr --;
+							this.currentCharacter = this.source[this.currentPosition++];
+						}
+						// we need to compute the escape character in a separate buffer
+						isRegex = scanRegexCharacter();
+						if (!isRegex) {
+							scanEscapeCharacter();
+						}
+						if (this.withoutUnicodePtr != 0) {
+							if (isRegex) {
+								char ch = this.currentCharacter;
+								this.currentCharacter = '\\';
+								unicodeStore();
+								this.currentCharacter = ch;
+							}
+							unicodeStore();
+						}
+					}
+					// consume next character
+					this.unicodeAsBackSlash = false;
+					if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+							&& (this.source[this.currentPosition] == 'u')) {
+						getNextUnicodeChar();
+						isUnicode = true;
+					} else {
+						isUnicode = false;
+						if (this.withoutUnicodePtr != 0) {
+							unicodeStore();
+						}
+					}
+
+				}
+			} catch (IndexOutOfBoundsException e) {
+				this.currentPosition--;
+				throw new InvalidInputException(UNTERMINATED_STRING);
+			} catch (InvalidInputException e) {
+				if (e.getMessage().equals(INVALID_ESCAPE)) {
+					// relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
+					for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
+						if (this.currentPosition + lookAhead == this.eofPosition)
+							break;
+						if (this.source[this.currentPosition + lookAhead] == '\n')
+							break;
+						if (this.source[this.currentPosition + lookAhead] == '\"') {
+							this.currentPosition += lookAhead + 1;
+							break;
+						}
+					}
+
+				}
+				throw e; // rethrow
+			}
+			return TokenNameStringLiteral;
+		} else {
+			return super.scanForStringLiteral();
+		}		
+	}
+	
+	@Override
+	protected int processSingleQuotes(boolean checkIfUnicode) throws InvalidInputException{
+		if (this.tokenizeSingleQuotes) {
+			return scanForSingleQuoteStringLiteral();
+		} else {
+			return super.processSingleQuotes(checkIfUnicode);
+		}
+	}
+
+	protected int scanForSingleQuoteStringLiteral() throws InvalidInputException {
+		this.unicodeAsBackSlash = false;
+		boolean isUnicode = false;
+		try {
+			// consume next character
+			this.unicodeAsBackSlash = false;
+			isUnicode = false;
+			if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+					&& (this.source[this.currentPosition] == 'u')) {
+				getNextUnicodeChar();
+				isUnicode = true;
+			} else {
+				if (this.withoutUnicodePtr != 0) {
+					unicodeStore();
+				}
+			}
+
+			while (this.currentCharacter != '\'') {
+				boolean isRegex = false;
+				if (this.currentPosition >= this.eofPosition) {
+					throw new InvalidInputException(UNTERMINATED_STRING);
+				}
+				/**** \r and \n are not valid in string literals ****/
+				if ((this.currentCharacter == '\n') || (this.currentCharacter == '\r')) {
+					// relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
+					if (isUnicode) {
+						int start = this.currentPosition;
+						for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
+							if (this.currentPosition >= this.eofPosition) {
+								this.currentPosition = start;
+								break;
+							}
+							if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
+								isUnicode = true;
+								getNextUnicodeChar();
+							} else {
+								isUnicode = false;
+							}
+							if (!isUnicode && this.currentCharacter == '\n') {
+								this.currentPosition--; // set current position on new line character
+								break;
+							}
+							if (this.currentCharacter == '\'') {
+								throw new InvalidInputException(INVALID_CHAR_IN_STRING);
+							}
+						}
+					} else {
+						this.currentPosition--; // set current position on new line character
+					}
+					throw new InvalidInputException(INVALID_CHAR_IN_STRING);
+				}
+				if (this.currentCharacter == '\\') {
+					if (this.unicodeAsBackSlash) {
+						this.withoutUnicodePtr--;
+						// consume next character
+						this.unicodeAsBackSlash = false;
+						if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
+							getNextUnicodeChar();
+							isUnicode = true;
+							this.withoutUnicodePtr--;
+						} else {
+							isUnicode = false;
+						}
+					} else {
+						if (this.withoutUnicodePtr == 0) {
+							unicodeInitializeBuffer(this.currentPosition - this.startPosition);
+						}
+						this.withoutUnicodePtr --;
+						this.currentCharacter = this.source[this.currentPosition++];
+					}
+					// we need to compute the escape character in a separate buffer
+					if (this.considerRegexInStringLiteral) {
+						isRegex = scanRegexCharacter();
+					}
+					if (!isRegex) {
+						scanEscapeCharacter();
+					}
+					if (this.withoutUnicodePtr != 0) {
+						if (isRegex) {
+							char ch = this.currentCharacter;
+							this.currentCharacter = '\\';
+							unicodeStore();
+							this.currentCharacter = ch;
+						}
+						unicodeStore();
+					}
+				}
+				// consume next character
+				this.unicodeAsBackSlash = false;
+				if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+						&& (this.source[this.currentPosition] == 'u')) {
+					getNextUnicodeChar();
+					isUnicode = true;
+				} else {
+					isUnicode = false;
+					if (this.withoutUnicodePtr != 0) {
+						unicodeStore();
+					}
+				}
+
+			}
+		} catch (IndexOutOfBoundsException e) {
+			this.currentPosition--;
+			throw new InvalidInputException(UNTERMINATED_STRING);
+		} catch (InvalidInputException e) {
+			if (e.getMessage().equals(INVALID_ESCAPE)) {
+				// relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
+				for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
+					if (this.currentPosition + lookAhead == this.eofPosition)
+						break;
+					if (this.source[this.currentPosition + lookAhead] == '\n')
+						break;
+					if (this.source[this.currentPosition + lookAhead] == '\'') {
+						this.currentPosition += lookAhead + 1;
+						break;
+					}
+				}
+
+			}
+			throw e; // rethrow
+		}
+		return TokenNameSingleQuoteStringLiteral;		
+	}
+
+	protected boolean scanRegexCharacter() {
+		boolean isRegex = false;
+		switch (this.currentCharacter) {
+			case 'd' :
+			case 'D' :
+			case 's' :
+			case 'S' :
+			case 'w' :
+			case 'W' :
+			case 'p' :
+			case 'b' :
+			case 'B' :
+			case 'A' :
+			case 'G' :
+			case 'z' :
+			case 'Z' :
+			case 'Q' :
+			case 'E' :
+			case 'a' :
+			case 'e' :
+				isRegex = true;
+				break;
+			default:
+				//do nothing
+		}
+		return isRegex;
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocTagConstants.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocTagConstants.java
index 27b4566..e759113 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocTagConstants.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocTagConstants.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2020 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -54,6 +54,9 @@
 	public static final char[] TAG_API_NOTE = "apiNote".toCharArray(); //$NON-NLS-1$
 	public static final char[] TAG_IMPL_SPEC = "implSpec".toCharArray(); //$NON-NLS-1$
 	public static final char[] TAG_IMPL_NOTE = "implNote".toCharArray(); //$NON-NLS-1$
+	public static final char[] TAG_SNIPPET = "snippet".toCharArray(); //$NON-NLS-1$
+	public static final char[] TAG_HIGHLIGHT = "highlight".toCharArray(); //$NON-NLS-1$
+	public static final char[] TAG_REPLACE = "replace".toCharArray(); //$NON-NLS-1$
 
 	// tags lengthes
 	public static final int TAG_DEPRECATED_LENGTH = TAG_DEPRECATED.length;
@@ -85,6 +88,10 @@
 	public static final int TAG_API_NOTE_LENGTH = TAG_API_NOTE.length;
 	public static final int TAG_IMPL_SPEC_LENGTH = TAG_IMPL_SPEC.length;
 	public static final int TAG_IMPL_NOTE_LENGTH = TAG_IMPL_NOTE.length;
+	public static final int TAG_SNIPPET_LENGTH = TAG_SNIPPET.length;
+	public static final int TAG_HIGHLIGHT_LENGTH = TAG_HIGHLIGHT.length;
+	public static final int TAG_REPLACE_LENGTH = TAG_REPLACE.length;
+
 
 	// tags value
 	public static final int NO_TAG_VALUE = 0;
@@ -117,12 +124,15 @@
 	public static final int TAG_API_NOTE_VALUE = 27;
 	public static final int TAG_IMPL_SPEC_VALUE = 28;
 	public static final int TAG_IMPL_NOTE_VALUE = 29;
+	public static final int TAG_SNIPPET_VALUE = 30;
+	public static final int TAG_HIGHLIGHT_VALUE = 31;
+	public static final int TAG_REPLACE_VALUE = 32;
 	public static final int TAG_OTHERS_VALUE = 100;
 
 //{ObjectTeams: role tag
 	public static final char[] TAG_ROLE = "role".toCharArray(); //$NON-NLS-1$
 	public static final int TAG_ROLE_LENGTH = TAG_ROLE.length;
-	public static final int TAG_ROLE_VALUE = 30;
+	public static final int TAG_ROLE_VALUE = 33;
 // SH}
 
 	// Tag names array
@@ -157,8 +167,11 @@
 		TAG_API_NOTE,			/* 27 */
 		TAG_IMPL_SPEC,			/* 28 */
 		TAG_IMPL_NOTE,			/* 29 */
+		TAG_SNIPPET,			/* 30 */
+		TAG_HIGHLIGHT,			/* 31 */
+		TAG_REPLACE,			/* 32 */
 //{ObjectTeams: role tag:
-		TAG_ROLE, 				/* 30 */
+		TAG_ROLE, 				/* 33 */
 // SH}
 	};
 
@@ -180,6 +193,8 @@
 	 */
 	public final static int BLOCK_IDX = 0;
 	public final static int INLINE_IDX = 1;
+	public final static int SNIPPET_IDX = 2;
+
 
 	// href tag
 	public final static char[] HREF_TAG = {'h', 'r', 'e', 'f'};
@@ -228,6 +243,8 @@
 		{},
 		// since 17
 		{},
+		// since 18
+		{},
 	};
 	public static final char[][][] INLINE_TAGS = {
 		// since 1.0
@@ -265,15 +282,25 @@
 		//since 16
 		{},
 		//since 17
-		{}
+		{},
+		//since 18
+		{ TAG_SNIPPET }
 	};
+	public static final char[][][] IN_SNIPPET_TAGS = {
+		//since 18
+			{ TAG_HIGHLIGHT, TAG_REPLACE, TAG_LINK }
+	};
+	public final static int IN_SNIPPET_TAGS_LENGTH = IN_SNIPPET_TAGS.length;
 	public final static int INLINE_TAGS_LENGTH = INLINE_TAGS.length;
+	public final static int SNIPPET_TAGS_LENGTH = IN_SNIPPET_TAGS.length;
+
 	public final static int BLOCK_TAGS_LENGTH = BLOCK_TAGS.length;
 	public final static int ALL_TAGS_LENGTH = BLOCK_TAGS_LENGTH+INLINE_TAGS_LENGTH;
 
 	public final static short TAG_TYPE_NONE = 0;
 	public final static short TAG_TYPE_INLINE = 1;
 	public final static short TAG_TYPE_BLOCK = 2;
+	public final static short TAG_TYPE_IN_SNIPPET = 3;
 	public static final short[] JAVADOC_TAG_TYPE = {
 		TAG_TYPE_NONE, 		// NO_TAG_VALUE = 0;
 		TAG_TYPE_BLOCK,		// TAG_DEPRECATED_VALUE = 1;
@@ -305,8 +332,11 @@
 		TAG_TYPE_BLOCK,		// TAG_API_NOTE = 27;
 		TAG_TYPE_BLOCK,		// TAG_IMPL_SPEC = 28;
 		TAG_TYPE_BLOCK,		// TAG_IMPL_NOTE = 29;
+		TAG_TYPE_INLINE,	// TAG_SNIPPET_VALUE = 30;
+		TAG_TYPE_IN_SNIPPET,// TAG_HIGHLIGHT_VALUE = 31;
+		TAG_TYPE_IN_SNIPPET,// TAG_HIGHLIGHT_VALUE = 32;
 //{ObjectTeams: @role tag
-		TAG_TYPE_BLOCK,		// TAG_ROLE_VALUE = 30;
+		TAG_TYPE_BLOCK,		// TAG_ROLE_VALUE = 33;
 // SH}
 	};
 	/*
@@ -330,6 +360,9 @@
 		TAG_API_NOTE,
 		TAG_IMPL_SPEC,
 		TAG_IMPL_NOTE,
+		TAG_SNIPPET,
+		TAG_HIGHLIGHT,
+		TAG_REPLACE
 	};
 	public static final char[][] COMPILATION_UNIT_TAGS = {};
 	public static final char[][] CLASS_TAGS = {
@@ -354,6 +387,9 @@
 		TAG_API_NOTE,
 		TAG_IMPL_SPEC,
 		TAG_IMPL_NOTE,
+		TAG_SNIPPET,
+		TAG_HIGHLIGHT,
+		TAG_REPLACE,
 //{ObjectTeams: role tag:
 		TAG_ROLE,
 // SH}
@@ -378,6 +414,9 @@
 		TAG_API_NOTE,
 		TAG_IMPL_SPEC,
 		TAG_IMPL_NOTE,
+		TAG_SNIPPET,
+		TAG_HIGHLIGHT,
+		TAG_REPLACE
 	};
 	public static final char[][] METHOD_TAGS = {
 		TAG_SEE,
@@ -403,6 +442,9 @@
 		TAG_API_NOTE,
 		TAG_IMPL_SPEC,
 		TAG_IMPL_NOTE,
+		TAG_SNIPPET,
+		TAG_HIGHLIGHT,
+		TAG_REPLACE
 	};
 	public static final char[][] MODULE_TAGS = {
 			TAG_SEE,
@@ -426,5 +468,8 @@
 			TAG_API_NOTE,
 			TAG_IMPL_SPEC,
 			TAG_IMPL_NOTE,
+			TAG_SNIPPET,
+			TAG_HIGHLIGHT,
+			TAG_REPLACE
 		};
 }
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 87eae23..4ba8b83 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
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2021 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -277,6 +277,8 @@
 						compliance = ClassFileConstants.JDK16;
 					}  else if("17".equals(token)) { //$NON-NLS-1$
 						compliance = ClassFileConstants.JDK17;
+					}  else if("18".equals(token)) { //$NON-NLS-1$
+						compliance = ClassFileConstants.JDK18;
 					} else if("recovery".equals(token)) { //$NON-NLS-1$
 						compliance = ClassFileConstants.JDK_DEFERRED;
 					}
@@ -977,9 +979,9 @@
 	protected int forStartPosition = 0;
 
 	protected int nestedType, dimensions, switchNestingLevel;
-	/* package */ int caseLevel;
-	protected int casePtr;
-	protected int[] caseStack;
+//	/* package */ int caseLevel;
+//	protected int casePtr;
+	protected Map<Integer, Integer> caseStartMap = new HashMap<>();
 	ASTNode [] noAstNodes = new ASTNode[AstStackIncrement];
 	public boolean switchWithTry = false;
 
@@ -1031,6 +1033,7 @@
 protected boolean parsingJava14Plus;
 protected boolean parsingJava15Plus;
 protected boolean parsingJava17Plus;
+protected boolean parsingJava18Plus;
 protected boolean previewEnabled;
 protected boolean parsingJava11Plus;
 protected int unstackedAct = ERROR_ACTION;
@@ -1065,13 +1068,13 @@
 	this.parsingJava14Plus = this.options.sourceLevel >= ClassFileConstants.JDK14;
 	this.parsingJava15Plus = this.options.sourceLevel >= ClassFileConstants.JDK15;
 	this.parsingJava17Plus = this.options.sourceLevel >= ClassFileConstants.JDK17;
+	this.parsingJava18Plus = this.options.sourceLevel >= ClassFileConstants.JDK18;
 	this.previewEnabled = this.options.sourceLevel == ClassFileConstants.getLatestJDKLevel() && this.options.enablePreviewFeatures;
 	this.astLengthStack = new int[50];
 	this.patternLengthStack = new int[20];
 	this.expressionLengthStack = new int[30];
 	this.typeAnnotationLengthStack = new int[30];
 	this.intStack = new int[50];
-	this.caseStack = new int[16];
 	this.identifierStack = new char[30][];
 	this.identifierLengthStack = new int[30];
 	this.nestedMethod = new int[30];
@@ -3101,11 +3104,16 @@
 	if (hasLeadingTagComment(FALL_THROUGH_TAG, caseStatement.sourceStart)) {
 		caseStatement.bits |= ASTNode.DocumentedFallthrough;
 	}
-	this.casePtr--;
-	this.scanner.caseStartPosition = this.casePtr >= 0 ? this.caseStack[this.casePtr] : -1;
+	this.scanner.caseStartPosition =  resetCaseStartAndPopPrev(this.switchNestingLevel);
 
 	pushOnAstStack(caseStatement);
 }
+private int resetCaseStartAndPopPrev(int nestingLevel) {
+	if (nestingLevel >= 0)
+		this.caseStartMap.put(nestingLevel, -1);
+
+	return this.caseStartMap.containsKey(nestingLevel - 1) ? this.caseStartMap.get(nestingLevel - 1): -1;
+}
 protected void consumeCastExpressionLL1() {
 	//CastExpression ::= '(' Name ')' InsideCastExpressionLL1 UnaryExpressionNotPlusMinus
 
@@ -5613,10 +5621,7 @@
 	// consume annotations
 	if (length > 0) {
 		Pattern pattern = (Pattern) this.patternStack[this.patternPtr--];
-		this.expressionStack[this.expressionPtr] = exp =
-				new InstanceOfExpression(
-					this.expressionStack[this.expressionPtr],
-					pattern);
+		exp = consumePatternInsideInstanceof(pattern);
 	} else {
 		TypeReference typeRef = (TypeReference) this.expressionStack[this.expressionPtr--];
 		this.expressionLengthPtr--;
@@ -5633,6 +5638,29 @@
 		exp.sourceEnd = this.scanner.startPosition - 1;
 	}
 }
+private Expression consumePatternInsideInstanceof(Pattern pattern) {
+	Expression exp;
+	if (pattern instanceof GuardedPattern) {
+		// This is a workaround as InstanceOfExpression doesn't handle a guarded pattern
+		// We alter the AST to look simpler
+		// As a result of this, the following code
+		//      str instanceof (String a && a == null)
+		// will be taken as
+		//     (str instanceof String a) && a == null
+		GuardedPattern gPattern = (GuardedPattern) pattern;
+		Expression insExpr = new InstanceOfExpression(
+								this.expressionStack[this.expressionPtr],
+									gPattern.primaryPattern);
+		AND_AND_Expression andExpression = new AND_AND_Expression(insExpr, gPattern.condition, OperatorIds.AND_AND);
+		this.expressionStack[this.expressionPtr] = exp = andExpression;
+	} else {
+		this.expressionStack[this.expressionPtr] = exp =
+			new InstanceOfExpression(
+				this.expressionStack[this.expressionPtr],
+				pattern);
+	}
+	return exp;
+}
 protected void consumeTypeReferenceWithModifiersAndAnnotations() {
 	// RelationalExpression ::= RelationalExpression 'instanceof' ReferenceType
 	//optimize the push/pop
@@ -5710,10 +5738,7 @@
 	if (length != 0) {
 		Pattern pattern = (Pattern) this.patternStack[this.patternPtr--];
 		pushOnExpressionStack(getUnspecifiedReferenceOptimized());
-		this.expressionStack[this.expressionPtr] = exp =
-				new InstanceOfExpression(
-					this.expressionStack[this.expressionPtr],
-					pattern);
+		exp = consumePatternInsideInstanceof(pattern);
 	} else {
 	//by construction, no base type may be used in getTypeReference
 		TypeReference typeRef = (TypeReference) this.expressionStack[this.expressionPtr--];
@@ -8448,6 +8473,10 @@
 	//ref.bits |= ASTNode.IsCapturedOuterLocal;
 	pushOnAstStack(ref);
  }
+protected void consumeResourceAsThis() {
+	Reference ref = new ThisReference(this.intStack[this.intPtr--], this.endPosition);
+	pushOnAstStack(ref);
+}
 protected void consumeResourceAsFieldAccess() {
 	// Resource ::= FieldAccess
 	FieldReference ref = (FieldReference) this.expressionStack[this.expressionPtr--];
@@ -9871,1375 +9900,1379 @@
 		    consumeResourceAsLocalVariable();
 			break;
 
-    case 620 : if (DEBUG) { System.out.println("Resource ::= FieldAccess"); }  //$NON-NLS-1$
+    case 620 : if (DEBUG) { System.out.println("Resource ::= this"); }  //$NON-NLS-1$
+		    consumeResourceAsThis();
+			break;
+
+    case 621 : if (DEBUG) { System.out.println("Resource ::= FieldAccess"); }  //$NON-NLS-1$
 		    consumeResourceAsFieldAccess();
 			break;
 
-    case 622 : if (DEBUG) { System.out.println("ExitTryBlock ::="); }  //$NON-NLS-1$
+    case 623 : if (DEBUG) { System.out.println("ExitTryBlock ::="); }  //$NON-NLS-1$
 		    consumeExitTryBlock();
 			break;
 
-    case 624 : if (DEBUG) { System.out.println("Catches ::= Catches CatchClause"); }  //$NON-NLS-1$
+    case 625 : if (DEBUG) { System.out.println("Catches ::= Catches CatchClause"); }  //$NON-NLS-1$
 		    consumeCatches();
 			break;
 
-    case 625 : if (DEBUG) { System.out.println("CatchClause ::= catch LPAREN CatchFormalParameter RPAREN"); }  //$NON-NLS-1$
+    case 626 : if (DEBUG) { System.out.println("CatchClause ::= catch LPAREN CatchFormalParameter RPAREN"); }  //$NON-NLS-1$
 		    consumeStatementCatch() ;
 			break;
 
-    case 627 : if (DEBUG) { System.out.println("PushLPAREN ::= LPAREN"); }  //$NON-NLS-1$
+    case 628 : if (DEBUG) { System.out.println("PushLPAREN ::= LPAREN"); }  //$NON-NLS-1$
 		    consumeLeftParen();
 			break;
 
-    case 628 : if (DEBUG) { System.out.println("PushRPAREN ::= RPAREN"); }  //$NON-NLS-1$
+    case 629 : if (DEBUG) { System.out.println("PushRPAREN ::= RPAREN"); }  //$NON-NLS-1$
 		    consumeRightParen();
 			break;
 
-    case 633 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= this"); }  //$NON-NLS-1$
+    case 634 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= this"); }  //$NON-NLS-1$
 		    consumePrimaryNoNewArrayThis();
 			break;
 
-    case 634 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PushLPAREN Expression_NotName..."); }  //$NON-NLS-1$
+    case 635 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PushLPAREN Expression_NotName..."); }  //$NON-NLS-1$
 		    consumePrimaryNoNewArray();
 			break;
 
-    case 635 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PushLPAREN Name PushRPAREN"); }  //$NON-NLS-1$
+    case 636 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PushLPAREN Name PushRPAREN"); }  //$NON-NLS-1$
 		    consumePrimaryNoNewArrayWithName();
 			break;
 
-    case 639 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name DOT this"); }  //$NON-NLS-1$
+    case 640 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name DOT this"); }  //$NON-NLS-1$
 		    consumePrimaryNoNewArrayNameThis();
 			break;
 
-    case 640 : if (DEBUG) { System.out.println("QualifiedSuperReceiver ::= Name DOT super"); }  //$NON-NLS-1$
+    case 641 : if (DEBUG) { System.out.println("QualifiedSuperReceiver ::= Name DOT super"); }  //$NON-NLS-1$
 		    consumeQualifiedSuperReceiver();
 			break;
 
-    case 641 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name DOT class"); }  //$NON-NLS-1$
+    case 642 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name DOT class"); }  //$NON-NLS-1$
 		    consumePrimaryNoNewArrayName();
 			break;
 
-    case 642 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name Dims DOT class"); }  //$NON-NLS-1$
+    case 643 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name Dims DOT class"); }  //$NON-NLS-1$
 		    consumePrimaryNoNewArrayArrayType();
 			break;
 
-    case 643 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PrimitiveType Dims DOT class"); }  //$NON-NLS-1$
+    case 644 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PrimitiveType Dims DOT class"); }  //$NON-NLS-1$
 		    consumePrimaryNoNewArrayPrimitiveArrayType();
 			break;
 
-    case 644 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PrimitiveType DOT class"); }  //$NON-NLS-1$
+    case 645 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PrimitiveType DOT class"); }  //$NON-NLS-1$
 		    consumePrimaryNoNewArrayPrimitiveType();
 			break;
 
-    case 645 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression LESS..."); }  //$NON-NLS-1$
+    case 646 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression LESS..."); }  //$NON-NLS-1$
 		    consumeRoleClassLiteral();
 			break;
 
-    case 651 : if (DEBUG) { System.out.println("ReferenceExpressionTypeArgumentsAndTrunk0 ::=..."); }  //$NON-NLS-1$
+    case 652 : if (DEBUG) { System.out.println("ReferenceExpressionTypeArgumentsAndTrunk0 ::=..."); }  //$NON-NLS-1$
 		    consumeReferenceExpressionTypeArgumentsAndTrunk(false);
 			break;
 
-    case 652 : if (DEBUG) { System.out.println("ReferenceExpressionTypeArgumentsAndTrunk0 ::=..."); }  //$NON-NLS-1$
+    case 653 : if (DEBUG) { System.out.println("ReferenceExpressionTypeArgumentsAndTrunk0 ::=..."); }  //$NON-NLS-1$
 		    consumeReferenceExpressionTypeArgumentsAndTrunk(true);
 			break;
 
-    case 653 : if (DEBUG) { System.out.println("ReferenceExpression ::= PrimitiveType Dims COLON_COLON"); }  //$NON-NLS-1$
+    case 654 : if (DEBUG) { System.out.println("ReferenceExpression ::= PrimitiveType Dims COLON_COLON"); }  //$NON-NLS-1$
 		    consumeReferenceExpressionTypeForm(true);
 			break;
 
-    case 654 : if (DEBUG) { System.out.println("ReferenceExpression ::= Name Dimsopt COLON_COLON..."); }  //$NON-NLS-1$
+    case 655 : if (DEBUG) { System.out.println("ReferenceExpression ::= Name Dimsopt COLON_COLON..."); }  //$NON-NLS-1$
 		    consumeReferenceExpressionTypeForm(false);
 			break;
 
-    case 655 : if (DEBUG) { System.out.println("ReferenceExpression ::= Name BeginTypeArguments..."); }  //$NON-NLS-1$
+    case 656 : if (DEBUG) { System.out.println("ReferenceExpression ::= Name BeginTypeArguments..."); }  //$NON-NLS-1$
 		    consumeReferenceExpressionGenericTypeForm();
 			break;
 
-    case 656 : if (DEBUG) { System.out.println("ReferenceExpression ::= Primary COLON_COLON..."); }  //$NON-NLS-1$
+    case 657 : if (DEBUG) { System.out.println("ReferenceExpression ::= Primary COLON_COLON..."); }  //$NON-NLS-1$
 		    consumeReferenceExpressionPrimaryForm();
 			break;
 
-    case 657 : if (DEBUG) { System.out.println("ReferenceExpression ::= QualifiedSuperReceiver..."); }  //$NON-NLS-1$
+    case 658 : if (DEBUG) { System.out.println("ReferenceExpression ::= QualifiedSuperReceiver..."); }  //$NON-NLS-1$
 		    consumeReferenceExpressionPrimaryForm();
 			break;
 
-    case 658 : if (DEBUG) { System.out.println("ReferenceExpression ::= super COLON_COLON..."); }  //$NON-NLS-1$
+    case 659 : if (DEBUG) { System.out.println("ReferenceExpression ::= super COLON_COLON..."); }  //$NON-NLS-1$
 		    consumeReferenceExpressionSuperForm();
 			break;
 
-    case 659 : if (DEBUG) { System.out.println("NonWildTypeArgumentsopt ::="); }  //$NON-NLS-1$
+    case 660 : if (DEBUG) { System.out.println("NonWildTypeArgumentsopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyTypeArguments();
 			break;
 
-    case 661 : if (DEBUG) { System.out.println("IdentifierOrNew ::= Identifier"); }  //$NON-NLS-1$
+    case 662 : if (DEBUG) { System.out.println("IdentifierOrNew ::= Identifier"); }  //$NON-NLS-1$
 		    consumeIdentifierOrNew(false);
 			break;
 
-    case 662 : if (DEBUG) { System.out.println("IdentifierOrNew ::= new"); }  //$NON-NLS-1$
+    case 663 : if (DEBUG) { System.out.println("IdentifierOrNew ::= new"); }  //$NON-NLS-1$
 		    consumeIdentifierOrNew(true);
 			break;
 
-    case 663 : if (DEBUG) { System.out.println("LambdaExpression ::= LambdaParameters ARROW EnterLambda"); }  //$NON-NLS-1$
+    case 664 : if (DEBUG) { System.out.println("LambdaExpression ::= LambdaParameters ARROW EnterLambda"); }  //$NON-NLS-1$
 		    consumeLambdaExpression();
 			break;
 
-    case 664 : if (DEBUG) { System.out.println("EnterLambda ::="); }  //$NON-NLS-1$
+    case 665 : if (DEBUG) { System.out.println("EnterLambda ::="); }  //$NON-NLS-1$
 		    consumeLambdaHeader();
 			break;
 
-    case 665 : if (DEBUG) { System.out.println("NestedLambda ::="); }  //$NON-NLS-1$
+    case 666 : if (DEBUG) { System.out.println("NestedLambda ::="); }  //$NON-NLS-1$
 		    consumeNestedLambda();
 			break;
 
-    case 666 : if (DEBUG) { System.out.println("LambdaParameters ::= Identifier NestedLambda"); }  //$NON-NLS-1$
+    case 667 : if (DEBUG) { System.out.println("LambdaParameters ::= Identifier NestedLambda"); }  //$NON-NLS-1$
 		    consumeTypeElidedLambdaParameter(false);
 			break;
 
-    case 672 : if (DEBUG) { System.out.println("TypeElidedFormalParameterList ::=..."); }  //$NON-NLS-1$
+    case 673 : if (DEBUG) { System.out.println("TypeElidedFormalParameterList ::=..."); }  //$NON-NLS-1$
 		    consumeFormalParameterList();
 			break;
 
-    case 673 : if (DEBUG) { System.out.println("TypeElidedFormalParameter ::= Modifiersopt Identifier"); }  //$NON-NLS-1$
+    case 674 : if (DEBUG) { System.out.println("TypeElidedFormalParameter ::= Modifiersopt Identifier"); }  //$NON-NLS-1$
 		    consumeTypeElidedLambdaParameter(true);
 			break;
 
-    case 676 : if (DEBUG) { System.out.println("ElidedLeftBraceAndReturn ::="); }  //$NON-NLS-1$
+    case 677 : if (DEBUG) { System.out.println("ElidedLeftBraceAndReturn ::="); }  //$NON-NLS-1$
 		    consumeElidedLeftBraceAndReturn();
 			break;
 
-    case 677 : if (DEBUG) { System.out.println("AllocationHeader ::= new ClassType LPAREN..."); }  //$NON-NLS-1$
+    case 678 : if (DEBUG) { System.out.println("AllocationHeader ::= new ClassType LPAREN..."); }  //$NON-NLS-1$
 		    consumeAllocationHeader();
 			break;
 
-    case 678 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= new..."); }  //$NON-NLS-1$
+    case 679 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= new..."); }  //$NON-NLS-1$
 		    consumeClassInstanceCreationExpressionWithTypeArguments();
 			break;
 
-    case 679 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= new ClassType..."); }  //$NON-NLS-1$
+    case 680 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= new ClassType..."); }  //$NON-NLS-1$
 		    consumeClassInstanceCreationExpression();
 			break;
 
-    case 680 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= Primary DOT new..."); }  //$NON-NLS-1$
+    case 681 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= Primary DOT new..."); }  //$NON-NLS-1$
 		    consumeClassInstanceCreationExpressionQualifiedWithTypeArguments() ;
 			break;
 
-    case 681 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= Primary DOT new..."); }  //$NON-NLS-1$
-		    consumeClassInstanceCreationExpressionQualified() ;
-			break;
-
-    case 682 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::=..."); }  //$NON-NLS-1$
+    case 682 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= Primary DOT new..."); }  //$NON-NLS-1$
 		    consumeClassInstanceCreationExpressionQualified() ;
 			break;
 
     case 683 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::=..."); }  //$NON-NLS-1$
+		    consumeClassInstanceCreationExpressionQualified() ;
+			break;
+
+    case 684 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::=..."); }  //$NON-NLS-1$
 		    consumeClassInstanceCreationExpressionQualifiedWithTypeArguments() ;
 			break;
 
-    case 684 : if (DEBUG) { System.out.println("EnterInstanceCreationArgumentList ::="); }  //$NON-NLS-1$
+    case 685 : if (DEBUG) { System.out.println("EnterInstanceCreationArgumentList ::="); }  //$NON-NLS-1$
 		    consumeEnterInstanceCreationArgumentList();
 			break;
 
-    case 685 : if (DEBUG) { System.out.println("ClassInstanceCreationExpressionName ::= Name DOT new"); }  //$NON-NLS-1$
+    case 686 : if (DEBUG) { System.out.println("ClassInstanceCreationExpressionName ::= Name DOT new"); }  //$NON-NLS-1$
 		    consumeClassInstanceCreationExpressionName() ;
 			break;
 
-    case 686 : if (DEBUG) { System.out.println("UnqualifiedClassBodyopt ::="); }  //$NON-NLS-1$
+    case 687 : if (DEBUG) { System.out.println("UnqualifiedClassBodyopt ::="); }  //$NON-NLS-1$
 		    consumeClassBodyopt();
 			break;
 
-    case 688 : if (DEBUG) { System.out.println("UnqualifiedEnterAnonymousClassBody ::="); }  //$NON-NLS-1$
+    case 689 : if (DEBUG) { System.out.println("UnqualifiedEnterAnonymousClassBody ::="); }  //$NON-NLS-1$
 		    consumeEnterAnonymousClassBody(false);
 			break;
 
-    case 689 : if (DEBUG) { System.out.println("QualifiedClassBodyopt ::="); }  //$NON-NLS-1$
+    case 690 : if (DEBUG) { System.out.println("QualifiedClassBodyopt ::="); }  //$NON-NLS-1$
 		    consumeClassBodyopt();
 			break;
 
-    case 691 : if (DEBUG) { System.out.println("QualifiedEnterAnonymousClassBody ::="); }  //$NON-NLS-1$
+    case 692 : if (DEBUG) { System.out.println("QualifiedEnterAnonymousClassBody ::="); }  //$NON-NLS-1$
 		    consumeEnterAnonymousClassBody(true);
 			break;
 
-    case 693 : if (DEBUG) { System.out.println("ArgumentList ::= ArgumentList COMMA Expression"); }  //$NON-NLS-1$
+    case 694 : if (DEBUG) { System.out.println("ArgumentList ::= ArgumentList COMMA Expression"); }  //$NON-NLS-1$
 		    consumeArgumentList();
 			break;
 
-    case 694 : if (DEBUG) { System.out.println("ArrayCreationHeader ::= new PrimitiveType..."); }  //$NON-NLS-1$
+    case 695 : if (DEBUG) { System.out.println("ArrayCreationHeader ::= new PrimitiveType..."); }  //$NON-NLS-1$
 		    consumeArrayCreationHeader();
 			break;
 
-    case 695 : if (DEBUG) { System.out.println("ArrayCreationHeader ::= new ClassOrInterfaceType..."); }  //$NON-NLS-1$
+    case 696 : if (DEBUG) { System.out.println("ArrayCreationHeader ::= new ClassOrInterfaceType..."); }  //$NON-NLS-1$
 		    consumeArrayCreationHeader();
 			break;
 
-    case 696 : if (DEBUG) { System.out.println("ArrayCreationWithoutArrayInitializer ::= new..."); }  //$NON-NLS-1$
+    case 697 : if (DEBUG) { System.out.println("ArrayCreationWithoutArrayInitializer ::= new..."); }  //$NON-NLS-1$
 		    consumeArrayCreationExpressionWithoutInitializer();
 			break;
 
-    case 697 : if (DEBUG) { System.out.println("ArrayCreationWithArrayInitializer ::= new PrimitiveType"); }  //$NON-NLS-1$
+    case 698 : if (DEBUG) { System.out.println("ArrayCreationWithArrayInitializer ::= new PrimitiveType"); }  //$NON-NLS-1$
 		    consumeArrayCreationExpressionWithInitializer();
 			break;
 
-    case 698 : if (DEBUG) { System.out.println("ArrayCreationWithoutArrayInitializer ::= new..."); }  //$NON-NLS-1$
+    case 699 : if (DEBUG) { System.out.println("ArrayCreationWithoutArrayInitializer ::= new..."); }  //$NON-NLS-1$
 		    consumeArrayCreationExpressionWithoutInitializer();
 			break;
 
-    case 699 : if (DEBUG) { System.out.println("ArrayCreationWithArrayInitializer ::= new..."); }  //$NON-NLS-1$
+    case 700 : if (DEBUG) { System.out.println("ArrayCreationWithArrayInitializer ::= new..."); }  //$NON-NLS-1$
 		    consumeArrayCreationExpressionWithInitializer();
 			break;
 
-    case 701 : if (DEBUG) { System.out.println("DimWithOrWithOutExprs ::= DimWithOrWithOutExprs..."); }  //$NON-NLS-1$
+    case 702 : if (DEBUG) { System.out.println("DimWithOrWithOutExprs ::= DimWithOrWithOutExprs..."); }  //$NON-NLS-1$
 		    consumeDimWithOrWithOutExprs();
 			break;
 
-     case 703 : if (DEBUG) { System.out.println("DimWithOrWithOutExpr ::= TypeAnnotationsopt LBRACKET..."); }  //$NON-NLS-1$
+     case 704 : if (DEBUG) { System.out.println("DimWithOrWithOutExpr ::= TypeAnnotationsopt LBRACKET..."); }  //$NON-NLS-1$
 		    consumeDimWithOrWithOutExpr();
 			break;
 
-     case 704 : if (DEBUG) { System.out.println("Dims ::= DimsLoop"); }  //$NON-NLS-1$
+     case 705 : if (DEBUG) { System.out.println("Dims ::= DimsLoop"); }  //$NON-NLS-1$
 		    consumeDims();
 			break;
 
-     case 707 : if (DEBUG) { System.out.println("OneDimLoop ::= LBRACKET RBRACKET"); }  //$NON-NLS-1$
+     case 708 : if (DEBUG) { System.out.println("OneDimLoop ::= LBRACKET RBRACKET"); }  //$NON-NLS-1$
 		    consumeOneDimLoop(false);
 			break;
 
-     case 708 : if (DEBUG) { System.out.println("OneDimLoop ::= TypeAnnotations LBRACKET RBRACKET"); }  //$NON-NLS-1$
+     case 709 : if (DEBUG) { System.out.println("OneDimLoop ::= TypeAnnotations LBRACKET RBRACKET"); }  //$NON-NLS-1$
 		    consumeOneDimLoop(true);
 			break;
 
-    case 709 : if (DEBUG) { System.out.println("FieldAccess ::= Primary DOT Identifier"); }  //$NON-NLS-1$
+    case 710 : if (DEBUG) { System.out.println("FieldAccess ::= Primary DOT Identifier"); }  //$NON-NLS-1$
 		    consumeFieldAccess(false);
 			break;
 
-    case 710 : if (DEBUG) { System.out.println("FieldAccess ::= super DOT Identifier"); }  //$NON-NLS-1$
+    case 711 : if (DEBUG) { System.out.println("FieldAccess ::= super DOT Identifier"); }  //$NON-NLS-1$
 		    consumeFieldAccess(true);
 			break;
 
-    case 711 : if (DEBUG) { System.out.println("FieldAccess ::= QualifiedSuperReceiver DOT Identifier"); }  //$NON-NLS-1$
+    case 712 : if (DEBUG) { System.out.println("FieldAccess ::= QualifiedSuperReceiver DOT Identifier"); }  //$NON-NLS-1$
 		    consumeFieldAccess(false);
 			break;
 
-    case 712 : if (DEBUG) { System.out.println("MethodInvocation ::= Name LPAREN ArgumentListopt RPAREN"); }  //$NON-NLS-1$
+    case 713 : if (DEBUG) { System.out.println("MethodInvocation ::= Name LPAREN ArgumentListopt RPAREN"); }  //$NON-NLS-1$
 		    consumeMethodInvocationName();
 			break;
 
-    case 713 : if (DEBUG) { System.out.println("MethodInvocation ::= Name DOT OnlyTypeArguments..."); }  //$NON-NLS-1$
+    case 714 : if (DEBUG) { System.out.println("MethodInvocation ::= Name DOT OnlyTypeArguments..."); }  //$NON-NLS-1$
 		    consumeMethodInvocationNameWithTypeArguments();
 			break;
 
-    case 714 : if (DEBUG) { System.out.println("MethodInvocation ::= Primary DOT OnlyTypeArguments..."); }  //$NON-NLS-1$
+    case 715 : if (DEBUG) { System.out.println("MethodInvocation ::= Primary DOT OnlyTypeArguments..."); }  //$NON-NLS-1$
 		    consumeMethodInvocationPrimaryWithTypeArguments();
 			break;
 
-    case 715 : if (DEBUG) { System.out.println("MethodInvocation ::= Primary DOT Identifier LPAREN..."); }  //$NON-NLS-1$
-		    consumeMethodInvocationPrimary();
-			break;
-
-    case 716 : if (DEBUG) { System.out.println("MethodInvocation ::= QualifiedSuperReceiver DOT..."); }  //$NON-NLS-1$
+    case 716 : if (DEBUG) { System.out.println("MethodInvocation ::= Primary DOT Identifier LPAREN..."); }  //$NON-NLS-1$
 		    consumeMethodInvocationPrimary();
 			break;
 
     case 717 : if (DEBUG) { System.out.println("MethodInvocation ::= QualifiedSuperReceiver DOT..."); }  //$NON-NLS-1$
+		    consumeMethodInvocationPrimary();
+			break;
+
+    case 718 : if (DEBUG) { System.out.println("MethodInvocation ::= QualifiedSuperReceiver DOT..."); }  //$NON-NLS-1$
 		    consumeMethodInvocationPrimaryWithTypeArguments();
 			break;
 
-    case 718 : if (DEBUG) { System.out.println("MethodInvocation ::= super DOT OnlyTypeArguments..."); }  //$NON-NLS-1$
+    case 719 : if (DEBUG) { System.out.println("MethodInvocation ::= super DOT OnlyTypeArguments..."); }  //$NON-NLS-1$
 		    consumeMethodInvocationSuperWithTypeArguments();
 			break;
 
-    case 719 : if (DEBUG) { System.out.println("MethodInvocation ::= super DOT Identifier LPAREN..."); }  //$NON-NLS-1$
+    case 720 : if (DEBUG) { System.out.println("MethodInvocation ::= super DOT Identifier LPAREN..."); }  //$NON-NLS-1$
 		    consumeMethodInvocationSuper();
 			break;
 
-    case 720 : if (DEBUG) { System.out.println("MethodInvocation ::= tsuper DOT Identifier LPAREN..."); }  //$NON-NLS-1$
+    case 721 : if (DEBUG) { System.out.println("MethodInvocation ::= tsuper DOT Identifier LPAREN..."); }  //$NON-NLS-1$
 		    consumeMethodInvocationTSuper(UNQUALIFIED);
 			break;
 
-    case 721 : if (DEBUG) { System.out.println("MethodInvocation ::= tsuper DOT OnlyTypeArguments..."); }  //$NON-NLS-1$
+    case 722 : if (DEBUG) { System.out.println("MethodInvocation ::= tsuper DOT OnlyTypeArguments..."); }  //$NON-NLS-1$
 		    consumeMethodInvocationTSuperWithTypeArguments(0);
 			break;
 
-    case 722 : if (DEBUG) { System.out.println("MethodInvocation ::= Name DOT tsuper DOT Identifier..."); }  //$NON-NLS-1$
+    case 723 : if (DEBUG) { System.out.println("MethodInvocation ::= Name DOT tsuper DOT Identifier..."); }  //$NON-NLS-1$
 		    consumeMethodInvocationTSuper(QUALIFIED);
 			break;
 
-    case 723 : if (DEBUG) { System.out.println("MethodInvocation ::= Name DOT tsuper DOT..."); }  //$NON-NLS-1$
+    case 724 : if (DEBUG) { System.out.println("MethodInvocation ::= Name DOT tsuper DOT..."); }  //$NON-NLS-1$
 		    consumeMethodInvocationTSuperWithTypeArguments(2);
 			break;
 
-    case 724 : if (DEBUG) { System.out.println("MethodInvocation ::= base DOT Identifier LPAREN..."); }  //$NON-NLS-1$
+    case 725 : if (DEBUG) { System.out.println("MethodInvocation ::= base DOT Identifier LPAREN..."); }  //$NON-NLS-1$
 		    consumeMethodInvocationBase(false);
 			break;
 
-    case 725 : if (DEBUG) { System.out.println("MethodInvocation ::= base DOT OnlyTypeArguments..."); }  //$NON-NLS-1$
+    case 726 : if (DEBUG) { System.out.println("MethodInvocation ::= base DOT OnlyTypeArguments..."); }  //$NON-NLS-1$
 		    consumeMethodInvocationBaseWithTypeArguments(false);
 			break;
 
-    case 726 : if (DEBUG) { System.out.println("MethodInvocation ::= base DOT super DOT Identifier..."); }  //$NON-NLS-1$
+    case 727 : if (DEBUG) { System.out.println("MethodInvocation ::= base DOT super DOT Identifier..."); }  //$NON-NLS-1$
 		    consumeMethodInvocationBase(true);
 			break;
 
-    case 727 : if (DEBUG) { System.out.println("MethodInvocation ::= base DOT super DOT..."); }  //$NON-NLS-1$
+    case 728 : if (DEBUG) { System.out.println("MethodInvocation ::= base DOT super DOT..."); }  //$NON-NLS-1$
 		    consumeMethodInvocationBaseWithTypeArguments(true);
 			break;
 
-    case 728 : if (DEBUG) { System.out.println("ArrayAccess ::= Name LBRACKET Expression RBRACKET"); }  //$NON-NLS-1$
+    case 729 : if (DEBUG) { System.out.println("ArrayAccess ::= Name LBRACKET Expression RBRACKET"); }  //$NON-NLS-1$
 		    consumeArrayAccess(true);
 			break;
 
-    case 729 : if (DEBUG) { System.out.println("ArrayAccess ::= PrimaryNoNewArray LBRACKET Expression..."); }  //$NON-NLS-1$
+    case 730 : if (DEBUG) { System.out.println("ArrayAccess ::= PrimaryNoNewArray LBRACKET Expression..."); }  //$NON-NLS-1$
 		    consumeArrayAccess(false);
 			break;
 
-    case 730 : if (DEBUG) { System.out.println("ArrayAccess ::= ArrayCreationWithArrayInitializer..."); }  //$NON-NLS-1$
+    case 731 : if (DEBUG) { System.out.println("ArrayAccess ::= ArrayCreationWithArrayInitializer..."); }  //$NON-NLS-1$
 		    consumeArrayAccess(false);
 			break;
 
-    case 732 : if (DEBUG) { System.out.println("PostfixExpression ::= Name"); }  //$NON-NLS-1$
+    case 733 : if (DEBUG) { System.out.println("PostfixExpression ::= Name"); }  //$NON-NLS-1$
 		    consumePostfixExpression();
 			break;
 
-    case 735 : if (DEBUG) { System.out.println("PostIncrementExpression ::= PostfixExpression PLUS_PLUS"); }  //$NON-NLS-1$
+    case 736 : if (DEBUG) { System.out.println("PostIncrementExpression ::= PostfixExpression PLUS_PLUS"); }  //$NON-NLS-1$
 		    consumeUnaryExpression(OperatorIds.PLUS,true);
 			break;
 
-    case 736 : if (DEBUG) { System.out.println("PostDecrementExpression ::= PostfixExpression..."); }  //$NON-NLS-1$
+    case 737 : if (DEBUG) { System.out.println("PostDecrementExpression ::= PostfixExpression..."); }  //$NON-NLS-1$
 		    consumeUnaryExpression(OperatorIds.MINUS,true);
 			break;
 
-    case 737 : if (DEBUG) { System.out.println("PushPosition ::="); }  //$NON-NLS-1$
+    case 738 : if (DEBUG) { System.out.println("PushPosition ::="); }  //$NON-NLS-1$
 		    consumePushPosition();
 			break;
 
-    case 740 : if (DEBUG) { System.out.println("UnaryExpression ::= PLUS PushPosition UnaryExpression"); }  //$NON-NLS-1$
+    case 741 : if (DEBUG) { System.out.println("UnaryExpression ::= PLUS PushPosition UnaryExpression"); }  //$NON-NLS-1$
 		    consumeUnaryExpression(OperatorIds.PLUS);
 			break;
 
-    case 741 : if (DEBUG) { System.out.println("UnaryExpression ::= MINUS PushPosition UnaryExpression"); }  //$NON-NLS-1$
+    case 742 : if (DEBUG) { System.out.println("UnaryExpression ::= MINUS PushPosition UnaryExpression"); }  //$NON-NLS-1$
 		    consumeUnaryExpression(OperatorIds.MINUS);
 			break;
 
-    case 743 : if (DEBUG) { System.out.println("PreIncrementExpression ::= PLUS_PLUS PushPosition..."); }  //$NON-NLS-1$
+    case 744 : if (DEBUG) { System.out.println("PreIncrementExpression ::= PLUS_PLUS PushPosition..."); }  //$NON-NLS-1$
 		    consumeUnaryExpression(OperatorIds.PLUS,false);
 			break;
 
-    case 744 : if (DEBUG) { System.out.println("PreDecrementExpression ::= MINUS_MINUS PushPosition..."); }  //$NON-NLS-1$
+    case 745 : if (DEBUG) { System.out.println("PreDecrementExpression ::= MINUS_MINUS PushPosition..."); }  //$NON-NLS-1$
 		    consumeUnaryExpression(OperatorIds.MINUS,false);
 			break;
 
-    case 746 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus ::= TWIDDLE PushPosition..."); }  //$NON-NLS-1$
+    case 747 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus ::= TWIDDLE PushPosition..."); }  //$NON-NLS-1$
 		    consumeUnaryExpression(OperatorIds.TWIDDLE);
 			break;
 
-    case 747 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus ::= NOT PushPosition..."); }  //$NON-NLS-1$
+    case 748 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus ::= NOT PushPosition..."); }  //$NON-NLS-1$
 		    consumeUnaryExpression(OperatorIds.NOT);
 			break;
 
-    case 749 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN PrimitiveType Dimsopt..."); }  //$NON-NLS-1$
+    case 750 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN PrimitiveType Dimsopt..."); }  //$NON-NLS-1$
 		    consumeCastExpressionWithPrimitiveType();
 			break;
 
-    case 750 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name..."); }  //$NON-NLS-1$
+    case 751 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name..."); }  //$NON-NLS-1$
 		    consumeCastExpressionWithGenericsArray();
 			break;
 
-    case 751 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name..."); }  //$NON-NLS-1$
+    case 752 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name..."); }  //$NON-NLS-1$
 		    consumeCastExpressionWithQualifiedGenericsArray();
 			break;
 
-    case 752 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name PushRPAREN..."); }  //$NON-NLS-1$
+    case 753 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name PushRPAREN..."); }  //$NON-NLS-1$
 		    consumeCastExpressionLL1();
 			break;
 
-    case 753 : if (DEBUG) { System.out.println("CastExpression ::= BeginIntersectionCast PushLPAREN..."); }  //$NON-NLS-1$
+    case 754 : if (DEBUG) { System.out.println("CastExpression ::= BeginIntersectionCast PushLPAREN..."); }  //$NON-NLS-1$
 		    consumeCastExpressionLL1WithBounds();
 			break;
 
-    case 754 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name Dims..."); }  //$NON-NLS-1$
+    case 755 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name Dims..."); }  //$NON-NLS-1$
 		    consumeCastExpressionWithNameArray();
 			break;
 
-    case 755 : if (DEBUG) { System.out.println("AdditionalBoundsListOpt ::="); }  //$NON-NLS-1$
+    case 756 : if (DEBUG) { System.out.println("AdditionalBoundsListOpt ::="); }  //$NON-NLS-1$
 		    consumeZeroAdditionalBounds();
 			break;
 
-    case 759 : if (DEBUG) { System.out.println("OnlyTypeArgumentsForCastExpression ::= OnlyTypeArguments"); }  //$NON-NLS-1$
+    case 760 : if (DEBUG) { System.out.println("OnlyTypeArgumentsForCastExpression ::= OnlyTypeArguments"); }  //$NON-NLS-1$
 		    consumeOnlyTypeArgumentsForCastExpression();
 			break;
 
-    case 760 : if (DEBUG) { System.out.println("InsideCastExpression ::="); }  //$NON-NLS-1$
+    case 761 : if (DEBUG) { System.out.println("InsideCastExpression ::="); }  //$NON-NLS-1$
 		    consumeInsideCastExpression();
 			break;
 
-    case 761 : if (DEBUG) { System.out.println("InsideCastExpressionLL1 ::="); }  //$NON-NLS-1$
+    case 762 : if (DEBUG) { System.out.println("InsideCastExpressionLL1 ::="); }  //$NON-NLS-1$
 		    consumeInsideCastExpressionLL1();
 			break;
 
-    case 762 : if (DEBUG) { System.out.println("InsideCastExpressionLL1WithBounds ::="); }  //$NON-NLS-1$
+    case 763 : if (DEBUG) { System.out.println("InsideCastExpressionLL1WithBounds ::="); }  //$NON-NLS-1$
 		    consumeInsideCastExpressionLL1WithBounds ();
 			break;
 
-    case 763 : if (DEBUG) { System.out.println("InsideCastExpressionWithQualifiedGenerics ::="); }  //$NON-NLS-1$
+    case 764 : if (DEBUG) { System.out.println("InsideCastExpressionWithQualifiedGenerics ::="); }  //$NON-NLS-1$
 		    consumeInsideCastExpressionWithQualifiedGenerics();
 			break;
 
-    case 765 : if (DEBUG) { System.out.println("MultiplicativeExpression ::= MultiplicativeExpression..."); }  //$NON-NLS-1$
+    case 766 : if (DEBUG) { System.out.println("MultiplicativeExpression ::= MultiplicativeExpression..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.MULTIPLY);
 			break;
 
-    case 766 : if (DEBUG) { System.out.println("MultiplicativeExpression ::= MultiplicativeExpression..."); }  //$NON-NLS-1$
+    case 767 : if (DEBUG) { System.out.println("MultiplicativeExpression ::= MultiplicativeExpression..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.DIVIDE);
 			break;
 
-    case 767 : if (DEBUG) { System.out.println("MultiplicativeExpression ::= MultiplicativeExpression..."); }  //$NON-NLS-1$
+    case 768 : if (DEBUG) { System.out.println("MultiplicativeExpression ::= MultiplicativeExpression..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.REMAINDER);
 			break;
 
-    case 769 : if (DEBUG) { System.out.println("AdditiveExpression ::= AdditiveExpression PLUS..."); }  //$NON-NLS-1$
+    case 770 : if (DEBUG) { System.out.println("AdditiveExpression ::= AdditiveExpression PLUS..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.PLUS);
 			break;
 
-    case 770 : if (DEBUG) { System.out.println("AdditiveExpression ::= AdditiveExpression MINUS..."); }  //$NON-NLS-1$
+    case 771 : if (DEBUG) { System.out.println("AdditiveExpression ::= AdditiveExpression MINUS..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.MINUS);
 			break;
 
-    case 772 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression LEFT_SHIFT..."); }  //$NON-NLS-1$
+    case 773 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression LEFT_SHIFT..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.LEFT_SHIFT);
 			break;
 
-    case 773 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression RIGHT_SHIFT..."); }  //$NON-NLS-1$
+    case 774 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression RIGHT_SHIFT..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.RIGHT_SHIFT);
 			break;
 
-    case 774 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression UNSIGNED_RIGHT_SHIFT"); }  //$NON-NLS-1$
+    case 775 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression UNSIGNED_RIGHT_SHIFT"); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.UNSIGNED_RIGHT_SHIFT);
 			break;
 
-    case 776 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression LESS..."); }  //$NON-NLS-1$
+    case 777 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression LESS..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.LESS);
 			break;
 
-    case 777 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression GREATER..."); }  //$NON-NLS-1$
+    case 778 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression GREATER..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.GREATER);
 			break;
 
-    case 778 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression LESS_EQUAL"); }  //$NON-NLS-1$
+    case 779 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression LESS_EQUAL"); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.LESS_EQUAL);
 			break;
 
-    case 779 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression..."); }  //$NON-NLS-1$
+    case 780 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.GREATER_EQUAL);
 			break;
 
-    case 781 : if (DEBUG) { System.out.println("EqualityExpression ::= EqualityExpression EQUAL_EQUAL..."); }  //$NON-NLS-1$
+    case 782 : if (DEBUG) { System.out.println("EqualityExpression ::= EqualityExpression EQUAL_EQUAL..."); }  //$NON-NLS-1$
 		    consumeEqualityExpression(OperatorIds.EQUAL_EQUAL);
 			break;
 
-    case 782 : if (DEBUG) { System.out.println("EqualityExpression ::= EqualityExpression NOT_EQUAL..."); }  //$NON-NLS-1$
+    case 783 : if (DEBUG) { System.out.println("EqualityExpression ::= EqualityExpression NOT_EQUAL..."); }  //$NON-NLS-1$
 		    consumeEqualityExpression(OperatorIds.NOT_EQUAL);
 			break;
 
-    case 784 : if (DEBUG) { System.out.println("AndExpression ::= AndExpression AND EqualityExpression"); }  //$NON-NLS-1$
+    case 785 : if (DEBUG) { System.out.println("AndExpression ::= AndExpression AND EqualityExpression"); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.AND);
 			break;
 
-    case 786 : if (DEBUG) { System.out.println("ExclusiveOrExpression ::= ExclusiveOrExpression XOR..."); }  //$NON-NLS-1$
+    case 787 : if (DEBUG) { System.out.println("ExclusiveOrExpression ::= ExclusiveOrExpression XOR..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.XOR);
 			break;
 
-    case 788 : if (DEBUG) { System.out.println("InclusiveOrExpression ::= InclusiveOrExpression OR..."); }  //$NON-NLS-1$
+    case 789 : if (DEBUG) { System.out.println("InclusiveOrExpression ::= InclusiveOrExpression OR..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.OR);
 			break;
 
-    case 790 : if (DEBUG) { System.out.println("ConditionalAndExpression ::= ConditionalAndExpression..."); }  //$NON-NLS-1$
+    case 791 : if (DEBUG) { System.out.println("ConditionalAndExpression ::= ConditionalAndExpression..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.AND_AND);
 			break;
 
-    case 792 : if (DEBUG) { System.out.println("ConditionalOrExpression ::= ConditionalOrExpression..."); }  //$NON-NLS-1$
+    case 793 : if (DEBUG) { System.out.println("ConditionalOrExpression ::= ConditionalOrExpression..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.OR_OR);
 			break;
 
-    case 794 : if (DEBUG) { System.out.println("ConditionalExpression ::= ConditionalOrExpression..."); }  //$NON-NLS-1$
+    case 795 : if (DEBUG) { System.out.println("ConditionalExpression ::= ConditionalOrExpression..."); }  //$NON-NLS-1$
 		    consumeConditionalExpression(OperatorIds.QUESTIONCOLON) ;
 			break;
 
-    case 797 : if (DEBUG) { System.out.println("Assignment ::= PostfixExpression AssignmentOperator..."); }  //$NON-NLS-1$
+    case 798 : if (DEBUG) { System.out.println("Assignment ::= PostfixExpression AssignmentOperator..."); }  //$NON-NLS-1$
 		    consumeAssignment();
 			break;
 
-    case 799 : if (DEBUG) { System.out.println("Assignment ::= InvalidArrayInitializerAssignement"); }  //$NON-NLS-1$
+    case 800 : if (DEBUG) { System.out.println("Assignment ::= InvalidArrayInitializerAssignement"); }  //$NON-NLS-1$
 		    ignoreExpressionAssignment();
 			break;
 
-    case 800 : if (DEBUG) { System.out.println("AssignmentOperator ::= EQUAL"); }  //$NON-NLS-1$
+    case 801 : if (DEBUG) { System.out.println("AssignmentOperator ::= EQUAL"); }  //$NON-NLS-1$
 		    consumeAssignmentOperator(EQUAL);
 			break;
 
-    case 801 : if (DEBUG) { System.out.println("AssignmentOperator ::= MULTIPLY_EQUAL"); }  //$NON-NLS-1$
+    case 802 : if (DEBUG) { System.out.println("AssignmentOperator ::= MULTIPLY_EQUAL"); }  //$NON-NLS-1$
 		    consumeAssignmentOperator(MULTIPLY);
 			break;
 
-    case 802 : if (DEBUG) { System.out.println("AssignmentOperator ::= DIVIDE_EQUAL"); }  //$NON-NLS-1$
+    case 803 : if (DEBUG) { System.out.println("AssignmentOperator ::= DIVIDE_EQUAL"); }  //$NON-NLS-1$
 		    consumeAssignmentOperator(DIVIDE);
 			break;
 
-    case 803 : if (DEBUG) { System.out.println("AssignmentOperator ::= REMAINDER_EQUAL"); }  //$NON-NLS-1$
+    case 804 : if (DEBUG) { System.out.println("AssignmentOperator ::= REMAINDER_EQUAL"); }  //$NON-NLS-1$
 		    consumeAssignmentOperator(REMAINDER);
 			break;
 
-    case 804 : if (DEBUG) { System.out.println("AssignmentOperator ::= PLUS_EQUAL"); }  //$NON-NLS-1$
+    case 805 : if (DEBUG) { System.out.println("AssignmentOperator ::= PLUS_EQUAL"); }  //$NON-NLS-1$
 		    consumeAssignmentOperator(PLUS);
 			break;
 
-    case 805 : if (DEBUG) { System.out.println("AssignmentOperator ::= MINUS_EQUAL"); }  //$NON-NLS-1$
+    case 806 : if (DEBUG) { System.out.println("AssignmentOperator ::= MINUS_EQUAL"); }  //$NON-NLS-1$
 		    consumeAssignmentOperator(MINUS);
 			break;
 
-    case 806 : if (DEBUG) { System.out.println("AssignmentOperator ::= LEFT_SHIFT_EQUAL"); }  //$NON-NLS-1$
+    case 807 : if (DEBUG) { System.out.println("AssignmentOperator ::= LEFT_SHIFT_EQUAL"); }  //$NON-NLS-1$
 		    consumeAssignmentOperator(LEFT_SHIFT);
 			break;
 
-    case 807 : if (DEBUG) { System.out.println("AssignmentOperator ::= RIGHT_SHIFT_EQUAL"); }  //$NON-NLS-1$
+    case 808 : if (DEBUG) { System.out.println("AssignmentOperator ::= RIGHT_SHIFT_EQUAL"); }  //$NON-NLS-1$
 		    consumeAssignmentOperator(RIGHT_SHIFT);
 			break;
 
-    case 808 : if (DEBUG) { System.out.println("AssignmentOperator ::= UNSIGNED_RIGHT_SHIFT_EQUAL"); }  //$NON-NLS-1$
+    case 809 : if (DEBUG) { System.out.println("AssignmentOperator ::= UNSIGNED_RIGHT_SHIFT_EQUAL"); }  //$NON-NLS-1$
 		    consumeAssignmentOperator(UNSIGNED_RIGHT_SHIFT);
 			break;
 
-    case 809 : if (DEBUG) { System.out.println("AssignmentOperator ::= AND_EQUAL"); }  //$NON-NLS-1$
+    case 810 : if (DEBUG) { System.out.println("AssignmentOperator ::= AND_EQUAL"); }  //$NON-NLS-1$
 		    consumeAssignmentOperator(AND);
 			break;
 
-    case 810 : if (DEBUG) { System.out.println("AssignmentOperator ::= XOR_EQUAL"); }  //$NON-NLS-1$
+    case 811 : if (DEBUG) { System.out.println("AssignmentOperator ::= XOR_EQUAL"); }  //$NON-NLS-1$
 		    consumeAssignmentOperator(XOR);
 			break;
 
-    case 811 : if (DEBUG) { System.out.println("AssignmentOperator ::= OR_EQUAL"); }  //$NON-NLS-1$
+    case 812 : if (DEBUG) { System.out.println("AssignmentOperator ::= OR_EQUAL"); }  //$NON-NLS-1$
 		    consumeAssignmentOperator(OR);
 			break;
 
-    case 812 : if (DEBUG) { System.out.println("Expression ::= AssignmentExpression"); }  //$NON-NLS-1$
+    case 813 : if (DEBUG) { System.out.println("Expression ::= AssignmentExpression"); }  //$NON-NLS-1$
 		    consumeExpression();
 			break;
 
-    case 815 : if (DEBUG) { System.out.println("Expressionopt ::="); }  //$NON-NLS-1$
+    case 816 : if (DEBUG) { System.out.println("Expressionopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyExpression();
 			break;
 
-    case 820 : if (DEBUG) { System.out.println("ClassBodyDeclarationsopt ::="); }  //$NON-NLS-1$
+    case 821 : if (DEBUG) { System.out.println("ClassBodyDeclarationsopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyClassBodyDeclarationsopt();
 			break;
 
-    case 821 : if (DEBUG) { System.out.println("ClassBodyDeclarationsopt ::= NestedType..."); }  //$NON-NLS-1$
+    case 822 : if (DEBUG) { System.out.println("ClassBodyDeclarationsopt ::= NestedType..."); }  //$NON-NLS-1$
 		    consumeClassBodyDeclarationsopt();
 			break;
 
-     case 822 : if (DEBUG) { System.out.println("Modifiersopt ::="); }  //$NON-NLS-1$
+     case 823 : if (DEBUG) { System.out.println("Modifiersopt ::="); }  //$NON-NLS-1$
 		    consumeDefaultModifiers();
 			break;
 
-    case 823 : if (DEBUG) { System.out.println("Modifiersopt ::= Modifiers"); }  //$NON-NLS-1$
+    case 824 : if (DEBUG) { System.out.println("Modifiersopt ::= Modifiers"); }  //$NON-NLS-1$
 		    consumeModifiers();
 			break;
 
-    case 824 : if (DEBUG) { System.out.println("BlockStatementsopt ::="); }  //$NON-NLS-1$
+    case 825 : if (DEBUG) { System.out.println("BlockStatementsopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyBlockStatementsopt();
 			break;
 
-     case 826 : if (DEBUG) { System.out.println("Dimsopt ::="); }  //$NON-NLS-1$
+     case 827 : if (DEBUG) { System.out.println("Dimsopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyDimsopt();
 			break;
 
-     case 828 : if (DEBUG) { System.out.println("ArgumentListopt ::="); }  //$NON-NLS-1$
+     case 829 : if (DEBUG) { System.out.println("ArgumentListopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyArgumentListopt();
 			break;
 
-    case 832 : if (DEBUG) { System.out.println("FormalParameterListopt ::="); }  //$NON-NLS-1$
+    case 833 : if (DEBUG) { System.out.println("FormalParameterListopt ::="); }  //$NON-NLS-1$
 		    consumeFormalParameterListopt();
 			break;
 
-    case 839 : if (DEBUG) { System.out.println("ClassHeaderPermittedSubclasses ::=..."); }  //$NON-NLS-1$
+    case 840 : if (DEBUG) { System.out.println("ClassHeaderPermittedSubclasses ::=..."); }  //$NON-NLS-1$
 		    consumeClassHeaderPermittedSubclasses();
 			break;
 
-    case 842 : if (DEBUG) { System.out.println("InterfaceHeaderPermittedSubClassesAndSubInterfaces ::="); }  //$NON-NLS-1$
+    case 843 : if (DEBUG) { System.out.println("InterfaceHeaderPermittedSubClassesAndSubInterfaces ::="); }  //$NON-NLS-1$
 		    consumeInterfaceHeaderPermittedSubClassesAndSubInterfaces();
 			break;
 
-     case 843 : if (DEBUG) { System.out.println("InterfaceMemberDeclarationsopt ::="); }  //$NON-NLS-1$
+     case 844 : if (DEBUG) { System.out.println("InterfaceMemberDeclarationsopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyInterfaceMemberDeclarationsopt();
 			break;
 
-     case 844 : if (DEBUG) { System.out.println("InterfaceMemberDeclarationsopt ::= NestedType..."); }  //$NON-NLS-1$
+     case 845 : if (DEBUG) { System.out.println("InterfaceMemberDeclarationsopt ::= NestedType..."); }  //$NON-NLS-1$
 		    consumeInterfaceMemberDeclarationsopt();
 			break;
 
-    case 845 : if (DEBUG) { System.out.println("NestedType ::="); }  //$NON-NLS-1$
+    case 846 : if (DEBUG) { System.out.println("NestedType ::="); }  //$NON-NLS-1$
 		    consumeNestedType();
 			break;
 
-     case 846 : if (DEBUG) { System.out.println("ForInitopt ::="); }  //$NON-NLS-1$
+     case 847 : if (DEBUG) { System.out.println("ForInitopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyForInitopt();
 			break;
 
-     case 848 : if (DEBUG) { System.out.println("ForUpdateopt ::="); }  //$NON-NLS-1$
+     case 849 : if (DEBUG) { System.out.println("ForUpdateopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyForUpdateopt();
 			break;
 
-     case 852 : if (DEBUG) { System.out.println("Catchesopt ::="); }  //$NON-NLS-1$
+     case 853 : if (DEBUG) { System.out.println("Catchesopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyCatchesopt();
 			break;
 
-     case 854 : if (DEBUG) { System.out.println("EnumDeclaration ::= EnumHeader EnumBody"); }  //$NON-NLS-1$
+     case 855 : if (DEBUG) { System.out.println("EnumDeclaration ::= EnumHeader EnumBody"); }  //$NON-NLS-1$
 		    consumeEnumDeclaration();
 			break;
 
-     case 855 : if (DEBUG) { System.out.println("EnumHeader ::= EnumHeaderName ClassHeaderImplementsopt"); }  //$NON-NLS-1$
+     case 856 : if (DEBUG) { System.out.println("EnumHeader ::= EnumHeaderName ClassHeaderImplementsopt"); }  //$NON-NLS-1$
 		    consumeEnumHeader();
 			break;
 
-     case 856 : if (DEBUG) { System.out.println("EnumHeaderName ::= Modifiersopt enum Identifier"); }  //$NON-NLS-1$
+     case 857 : if (DEBUG) { System.out.println("EnumHeaderName ::= Modifiersopt enum Identifier"); }  //$NON-NLS-1$
 		    consumeEnumHeaderName();
 			break;
 
-     case 857 : if (DEBUG) { System.out.println("EnumHeaderName ::= Modifiersopt enum Identifier..."); }  //$NON-NLS-1$
+     case 858 : if (DEBUG) { System.out.println("EnumHeaderName ::= Modifiersopt enum Identifier..."); }  //$NON-NLS-1$
 		    consumeEnumHeaderNameWithTypeParameters();
 			break;
 
-     case 858 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumBodyDeclarationsopt RBRACE"); }  //$NON-NLS-1$
+     case 859 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumBodyDeclarationsopt RBRACE"); }  //$NON-NLS-1$
 		    consumeEnumBodyNoConstants();
 			break;
 
-     case 859 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE COMMA EnumBodyDeclarationsopt..."); }  //$NON-NLS-1$
+     case 860 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE COMMA EnumBodyDeclarationsopt..."); }  //$NON-NLS-1$
 		    consumeEnumBodyNoConstants();
 			break;
 
-     case 860 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumConstants COMMA..."); }  //$NON-NLS-1$
+     case 861 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumConstants COMMA..."); }  //$NON-NLS-1$
 		    consumeEnumBodyWithConstants();
 			break;
 
-     case 861 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumConstants..."); }  //$NON-NLS-1$
+     case 862 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumConstants..."); }  //$NON-NLS-1$
 		    consumeEnumBodyWithConstants();
 			break;
 
-    case 863 : if (DEBUG) { System.out.println("EnumConstants ::= EnumConstants COMMA EnumConstant"); }  //$NON-NLS-1$
+    case 864 : if (DEBUG) { System.out.println("EnumConstants ::= EnumConstants COMMA EnumConstant"); }  //$NON-NLS-1$
 		    consumeEnumConstants();
 			break;
 
-    case 864 : if (DEBUG) { System.out.println("EnumConstantHeaderName ::= Modifiersopt Identifier"); }  //$NON-NLS-1$
+    case 865 : if (DEBUG) { System.out.println("EnumConstantHeaderName ::= Modifiersopt Identifier"); }  //$NON-NLS-1$
 		    consumeEnumConstantHeaderName();
 			break;
 
-    case 865 : if (DEBUG) { System.out.println("EnumConstantHeader ::= EnumConstantHeaderName..."); }  //$NON-NLS-1$
+    case 866 : if (DEBUG) { System.out.println("EnumConstantHeader ::= EnumConstantHeaderName..."); }  //$NON-NLS-1$
 		    consumeEnumConstantHeader();
 			break;
 
-    case 866 : if (DEBUG) { System.out.println("EnumConstant ::= EnumConstantHeader ForceNoDiet..."); }  //$NON-NLS-1$
+    case 867 : if (DEBUG) { System.out.println("EnumConstant ::= EnumConstantHeader ForceNoDiet..."); }  //$NON-NLS-1$
 		    consumeEnumConstantWithClassBody();
 			break;
 
-    case 867 : if (DEBUG) { System.out.println("EnumConstant ::= EnumConstantHeader"); }  //$NON-NLS-1$
+    case 868 : if (DEBUG) { System.out.println("EnumConstant ::= EnumConstantHeader"); }  //$NON-NLS-1$
 		    consumeEnumConstantNoClassBody();
 			break;
 
-    case 868 : if (DEBUG) { System.out.println("Arguments ::= LPAREN ArgumentListopt RPAREN"); }  //$NON-NLS-1$
+    case 869 : if (DEBUG) { System.out.println("Arguments ::= LPAREN ArgumentListopt RPAREN"); }  //$NON-NLS-1$
 		    consumeArguments();
 			break;
 
-    case 869 : if (DEBUG) { System.out.println("Argumentsopt ::="); }  //$NON-NLS-1$
+    case 870 : if (DEBUG) { System.out.println("Argumentsopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyArguments();
 			break;
 
-    case 871 : if (DEBUG) { System.out.println("EnumDeclarations ::= SEMICOLON ClassBodyDeclarationsopt"); }  //$NON-NLS-1$
+    case 872 : if (DEBUG) { System.out.println("EnumDeclarations ::= SEMICOLON ClassBodyDeclarationsopt"); }  //$NON-NLS-1$
 		    consumeEnumDeclarations();
 			break;
 
-    case 872 : if (DEBUG) { System.out.println("EnumBodyDeclarationsopt ::="); }  //$NON-NLS-1$
+    case 873 : if (DEBUG) { System.out.println("EnumBodyDeclarationsopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyEnumDeclarations();
 			break;
 
-    case 874 : if (DEBUG) { System.out.println("EnhancedForStatement ::= EnhancedForStatementHeader..."); }  //$NON-NLS-1$
+    case 875 : if (DEBUG) { System.out.println("EnhancedForStatement ::= EnhancedForStatementHeader..."); }  //$NON-NLS-1$
 		    consumeEnhancedForStatement();
 			break;
 
-    case 875 : if (DEBUG) { System.out.println("EnhancedForStatementNoShortIf ::=..."); }  //$NON-NLS-1$
+    case 876 : if (DEBUG) { System.out.println("EnhancedForStatementNoShortIf ::=..."); }  //$NON-NLS-1$
 		    consumeEnhancedForStatement();
 			break;
 
-    case 876 : if (DEBUG) { System.out.println("EnhancedForStatementHeaderInit ::= for LPAREN Type..."); }  //$NON-NLS-1$
+    case 877 : if (DEBUG) { System.out.println("EnhancedForStatementHeaderInit ::= for LPAREN Type..."); }  //$NON-NLS-1$
 		    consumeEnhancedForStatementHeaderInit(false);
 			break;
 
-    case 877 : if (DEBUG) { System.out.println("EnhancedForStatementHeaderInit ::= for LPAREN Modifiers"); }  //$NON-NLS-1$
+    case 878 : if (DEBUG) { System.out.println("EnhancedForStatementHeaderInit ::= for LPAREN Modifiers"); }  //$NON-NLS-1$
 		    consumeEnhancedForStatementHeaderInit(true);
 			break;
 
-    case 878 : if (DEBUG) { System.out.println("EnhancedForStatementHeader ::=..."); }  //$NON-NLS-1$
+    case 879 : if (DEBUG) { System.out.println("EnhancedForStatementHeader ::=..."); }  //$NON-NLS-1$
 		    consumeEnhancedForStatementHeader();
 			break;
 
-    case 879 : if (DEBUG) { System.out.println("SingleBaseImportDeclaration ::=..."); }  //$NON-NLS-1$
+    case 880 : if (DEBUG) { System.out.println("SingleBaseImportDeclaration ::=..."); }  //$NON-NLS-1$
 		    consumeImportDeclaration();
 			break;
 
-    case 880 : if (DEBUG) { System.out.println("SingleBaseImportDeclarationName ::= import base Name"); }  //$NON-NLS-1$
+    case 881 : if (DEBUG) { System.out.println("SingleBaseImportDeclarationName ::= import base Name"); }  //$NON-NLS-1$
 		    consumeSingleBaseImportDeclarationName();
 			break;
 
-    case 881 : if (DEBUG) { System.out.println("SingleStaticImportDeclaration ::=..."); }  //$NON-NLS-1$
+    case 882 : if (DEBUG) { System.out.println("SingleStaticImportDeclaration ::=..."); }  //$NON-NLS-1$
 		    consumeImportDeclaration();
 			break;
 
-    case 882 : if (DEBUG) { System.out.println("SingleStaticImportDeclarationName ::= import static Name"); }  //$NON-NLS-1$
+    case 883 : if (DEBUG) { System.out.println("SingleStaticImportDeclarationName ::= import static Name"); }  //$NON-NLS-1$
 		    consumeSingleStaticImportDeclarationName();
 			break;
 
-    case 883 : if (DEBUG) { System.out.println("StaticImportOnDemandDeclaration ::=..."); }  //$NON-NLS-1$
+    case 884 : if (DEBUG) { System.out.println("StaticImportOnDemandDeclaration ::=..."); }  //$NON-NLS-1$
 		    consumeImportDeclaration();
 			break;
 
-    case 884 : if (DEBUG) { System.out.println("StaticImportOnDemandDeclarationName ::= import static..."); }  //$NON-NLS-1$
+    case 885 : if (DEBUG) { System.out.println("StaticImportOnDemandDeclarationName ::= import static..."); }  //$NON-NLS-1$
 		    consumeStaticImportOnDemandDeclarationName();
 			break;
 
-    case 885 : if (DEBUG) { System.out.println("TypeArguments ::= LESS TypeArgumentList1"); }  //$NON-NLS-1$
+    case 886 : if (DEBUG) { System.out.println("TypeArguments ::= LESS TypeArgumentList1"); }  //$NON-NLS-1$
 		    consumeTypeArguments();
 			break;
 
-    case 886 : if (DEBUG) { System.out.println("OnlyTypeArguments ::= LESS TypeArgumentList1"); }  //$NON-NLS-1$
+    case 887 : if (DEBUG) { System.out.println("OnlyTypeArguments ::= LESS TypeArgumentList1"); }  //$NON-NLS-1$
 		    consumeOnlyTypeArguments();
 			break;
 
-    case 888 : if (DEBUG) { System.out.println("TypeArgumentList1 ::= TypeArgumentList COMMA..."); }  //$NON-NLS-1$
+    case 889 : if (DEBUG) { System.out.println("TypeArgumentList1 ::= TypeArgumentList COMMA..."); }  //$NON-NLS-1$
 		    consumeTypeArgumentList1();
 			break;
 
-    case 890 : if (DEBUG) { System.out.println("TypeArgumentList ::= TypeArgumentList COMMA TypeArgument"); }  //$NON-NLS-1$
+    case 891 : if (DEBUG) { System.out.println("TypeArgumentList ::= TypeArgumentList COMMA TypeArgument"); }  //$NON-NLS-1$
 		    consumeTypeArgumentList();
 			break;
 
-    case 891 : if (DEBUG) { System.out.println("TypeArgument ::= ReferenceType"); }  //$NON-NLS-1$
+    case 892 : if (DEBUG) { System.out.println("TypeArgument ::= ReferenceType"); }  //$NON-NLS-1$
 		    consumeTypeArgument();
 			break;
 
-    case 897 : if (DEBUG) { System.out.println("TypeAnchorOrAnnotatedTypeArgument -> AnyTypeAnchor"); }  //$NON-NLS-1$
+    case 898 : if (DEBUG) { System.out.println("TypeAnchorOrAnnotatedTypeArgument -> AnyTypeAnchor"); }  //$NON-NLS-1$
 		    confirmTypeAnchor();
 			break;
 
-    case 898 : if (DEBUG) { System.out.println("TypeAnchorOrAnnotatedTypeArgument ::=..."); }  //$NON-NLS-1$
-		    consumeTypeArgumentFromAnchor();
-			break;
-
     case 899 : if (DEBUG) { System.out.println("TypeAnchorOrAnnotatedTypeArgument ::=..."); }  //$NON-NLS-1$
+		    consumeTypeArgumentFromAnchor();
+			break;
+
+    case 900 : if (DEBUG) { System.out.println("TypeAnchorOrAnnotatedTypeArgument ::=..."); }  //$NON-NLS-1$
 		    consumeAnnotationsOnTypeArgumentFromAnchor();
 			break;
 
-    case 900 : if (DEBUG) { System.out.println("TypeAnchorOrAnnotatedTypeArgument1 ::= AnyTypeAnchor..."); }  //$NON-NLS-1$
+    case 901 : if (DEBUG) { System.out.println("TypeAnchorOrAnnotatedTypeArgument1 ::= AnyTypeAnchor..."); }  //$NON-NLS-1$
 		    confirmTypeAnchor();
 			break;
 
-    case 901 : if (DEBUG) { System.out.println("TypeAnchorOrAnnotatedTypeArgument1 ::=..."); }  //$NON-NLS-1$
-		    consumeAnnotationsOnTypeArgumentFromAnchor();
-			break;
-
     case 902 : if (DEBUG) { System.out.println("TypeAnchorOrAnnotatedTypeArgument1 ::=..."); }  //$NON-NLS-1$
 		    consumeAnnotationsOnTypeArgumentFromAnchor();
 			break;
 
-    case 903 : if (DEBUG) { System.out.println("TypeAnchorOrAnnotatedTypeArgument2 ::= AnyTypeAnchor..."); }  //$NON-NLS-1$
-		    confirmTypeAnchor();
+    case 903 : if (DEBUG) { System.out.println("TypeAnchorOrAnnotatedTypeArgument1 ::=..."); }  //$NON-NLS-1$
+		    consumeAnnotationsOnTypeArgumentFromAnchor();
 			break;
 
-    case 904 : if (DEBUG) { System.out.println("TypeAnchorOrAnnotatedTypeArgument2 ::=..."); }  //$NON-NLS-1$
-		    consumeAnnotationsOnTypeArgumentFromAnchor();
+    case 904 : if (DEBUG) { System.out.println("TypeAnchorOrAnnotatedTypeArgument2 ::= AnyTypeAnchor..."); }  //$NON-NLS-1$
+		    confirmTypeAnchor();
 			break;
 
     case 905 : if (DEBUG) { System.out.println("TypeAnchorOrAnnotatedTypeArgument2 ::=..."); }  //$NON-NLS-1$
 		    consumeAnnotationsOnTypeArgumentFromAnchor();
 			break;
 
-    case 906 : if (DEBUG) { System.out.println("TypeAnchorOrAnnotatedTypeArgument3 ::= AnyTypeAnchor..."); }  //$NON-NLS-1$
-		    confirmTypeAnchor();
+    case 906 : if (DEBUG) { System.out.println("TypeAnchorOrAnnotatedTypeArgument2 ::=..."); }  //$NON-NLS-1$
+		    consumeAnnotationsOnTypeArgumentFromAnchor();
 			break;
 
-    case 907 : if (DEBUG) { System.out.println("TypeAnchorOrAnnotatedTypeArgument3 ::=..."); }  //$NON-NLS-1$
-		    consumeAnnotationsOnTypeArgumentFromAnchor();
+    case 907 : if (DEBUG) { System.out.println("TypeAnchorOrAnnotatedTypeArgument3 ::= AnyTypeAnchor..."); }  //$NON-NLS-1$
+		    confirmTypeAnchor();
 			break;
 
     case 908 : if (DEBUG) { System.out.println("TypeAnchorOrAnnotatedTypeArgument3 ::=..."); }  //$NON-NLS-1$
 		    consumeAnnotationsOnTypeArgumentFromAnchor();
 			break;
 
-    case 909 : if (DEBUG) { System.out.println("NotAnAnchor ::="); }  //$NON-NLS-1$
+    case 909 : if (DEBUG) { System.out.println("TypeAnchorOrAnnotatedTypeArgument3 ::=..."); }  //$NON-NLS-1$
+		    consumeAnnotationsOnTypeArgumentFromAnchor();
+			break;
+
+    case 910 : if (DEBUG) { System.out.println("NotAnAnchor ::="); }  //$NON-NLS-1$
 		    convertTypeAnchor(0);
 			break;
 
-    case 910 : if (DEBUG) { System.out.println("NotAnAnchor ::= LPAREN SingleMemberAnnotationMemberValue"); }  //$NON-NLS-1$
+    case 911 : if (DEBUG) { System.out.println("NotAnAnchor ::= LPAREN SingleMemberAnnotationMemberValue"); }  //$NON-NLS-1$
 		    convertTypeAnchor(1);
 			break;
 
-    case 911 : if (DEBUG) { System.out.println("NotAnAnchor ::= LPAREN MemberValuePairsopt RPAREN"); }  //$NON-NLS-1$
+    case 912 : if (DEBUG) { System.out.println("NotAnAnchor ::= LPAREN MemberValuePairsopt RPAREN"); }  //$NON-NLS-1$
 		    convertTypeAnchor(2);
 			break;
 
-    case 914 : if (DEBUG) { System.out.println("TentativeTypeAnchor ::= ATOT UnannotatableName"); }  //$NON-NLS-1$
+    case 915 : if (DEBUG) { System.out.println("TentativeTypeAnchor ::= ATOT UnannotatableName"); }  //$NON-NLS-1$
 		    consumeTypeAnchor(false);
 			break;
 
-    case 915 : if (DEBUG) { System.out.println("TypeAnchor ::= ATOT base"); }  //$NON-NLS-1$
+    case 916 : if (DEBUG) { System.out.println("TypeAnchor ::= ATOT base"); }  //$NON-NLS-1$
 		    consumeTypeAnchor(true);
 			break;
 
-    case 916 : if (DEBUG) { System.out.println("TypeAnchor ::= ATOT this"); }  //$NON-NLS-1$
+    case 917 : if (DEBUG) { System.out.println("TypeAnchor ::= ATOT this"); }  //$NON-NLS-1$
 		    skipThisAnchor();
 			break;
 
-    case 917 : if (DEBUG) { System.out.println("TypeAnchor ::= ATOT UnannotatableName DOT base"); }  //$NON-NLS-1$
+    case 918 : if (DEBUG) { System.out.println("TypeAnchor ::= ATOT UnannotatableName DOT base"); }  //$NON-NLS-1$
 		    consumeQualifiedBaseTypeAnchor();
 			break;
 
-    case 920 : if (DEBUG) { System.out.println("ReferenceType1 ::= ReferenceType GREATER"); }  //$NON-NLS-1$
+    case 921 : if (DEBUG) { System.out.println("ReferenceType1 ::= ReferenceType GREATER"); }  //$NON-NLS-1$
 		    consumeReferenceType1();
 			break;
 
-    case 921 : if (DEBUG) { System.out.println("ReferenceType1 ::= ClassOrInterface LESS..."); }  //$NON-NLS-1$
+    case 922 : if (DEBUG) { System.out.println("ReferenceType1 ::= ClassOrInterface LESS..."); }  //$NON-NLS-1$
 		    consumeTypeArgumentReferenceType1();
 			break;
 
-    case 923 : if (DEBUG) { System.out.println("TypeArgumentList2 ::= TypeArgumentList COMMA..."); }  //$NON-NLS-1$
+    case 924 : if (DEBUG) { System.out.println("TypeArgumentList2 ::= TypeArgumentList COMMA..."); }  //$NON-NLS-1$
 		    consumeTypeArgumentList2();
 			break;
 
-    case 926 : if (DEBUG) { System.out.println("ReferenceType2 ::= ReferenceType RIGHT_SHIFT"); }  //$NON-NLS-1$
+    case 927 : if (DEBUG) { System.out.println("ReferenceType2 ::= ReferenceType RIGHT_SHIFT"); }  //$NON-NLS-1$
 		    consumeReferenceType2();
 			break;
 
-    case 927 : if (DEBUG) { System.out.println("ReferenceType2 ::= ClassOrInterface LESS..."); }  //$NON-NLS-1$
+    case 928 : if (DEBUG) { System.out.println("ReferenceType2 ::= ClassOrInterface LESS..."); }  //$NON-NLS-1$
 		    consumeTypeArgumentReferenceType2();
 			break;
 
-    case 929 : if (DEBUG) { System.out.println("TypeArgumentList3 ::= TypeArgumentList COMMA..."); }  //$NON-NLS-1$
+    case 930 : if (DEBUG) { System.out.println("TypeArgumentList3 ::= TypeArgumentList COMMA..."); }  //$NON-NLS-1$
 		    consumeTypeArgumentList3();
 			break;
 
-    case 932 : if (DEBUG) { System.out.println("ReferenceType3 ::= ReferenceType UNSIGNED_RIGHT_SHIFT"); }  //$NON-NLS-1$
+    case 933 : if (DEBUG) { System.out.println("ReferenceType3 ::= ReferenceType UNSIGNED_RIGHT_SHIFT"); }  //$NON-NLS-1$
 		    consumeReferenceType3();
 			break;
 
-    case 933 : if (DEBUG) { System.out.println("Wildcard ::= TypeAnnotationsopt QUESTION"); }  //$NON-NLS-1$
+    case 934 : if (DEBUG) { System.out.println("Wildcard ::= TypeAnnotationsopt QUESTION"); }  //$NON-NLS-1$
 		    consumeWildcard();
 			break;
 
-    case 934 : if (DEBUG) { System.out.println("Wildcard ::= TypeAnnotationsopt QUESTION WildcardBounds"); }  //$NON-NLS-1$
+    case 935 : if (DEBUG) { System.out.println("Wildcard ::= TypeAnnotationsopt QUESTION WildcardBounds"); }  //$NON-NLS-1$
 		    consumeWildcardWithBounds();
 			break;
 
-    case 935 : if (DEBUG) { System.out.println("WildcardBounds ::= extends ReferenceType"); }  //$NON-NLS-1$
+    case 936 : if (DEBUG) { System.out.println("WildcardBounds ::= extends ReferenceType"); }  //$NON-NLS-1$
 		    consumeWildcardBoundsExtends();
 			break;
 
-    case 936 : if (DEBUG) { System.out.println("WildcardBounds ::= super ReferenceType"); }  //$NON-NLS-1$
+    case 937 : if (DEBUG) { System.out.println("WildcardBounds ::= super ReferenceType"); }  //$NON-NLS-1$
 		    consumeWildcardBoundsSuper();
 			break;
 
-    case 937 : if (DEBUG) { System.out.println("Wildcard1 ::= TypeAnnotationsopt QUESTION GREATER"); }  //$NON-NLS-1$
+    case 938 : if (DEBUG) { System.out.println("Wildcard1 ::= TypeAnnotationsopt QUESTION GREATER"); }  //$NON-NLS-1$
 		    consumeWildcard1();
 			break;
 
-    case 938 : if (DEBUG) { System.out.println("Wildcard1 ::= TypeAnnotationsopt QUESTION..."); }  //$NON-NLS-1$
+    case 939 : if (DEBUG) { System.out.println("Wildcard1 ::= TypeAnnotationsopt QUESTION..."); }  //$NON-NLS-1$
 		    consumeWildcard1WithBounds();
 			break;
 
-    case 939 : if (DEBUG) { System.out.println("WildcardBounds1 ::= extends ReferenceType1"); }  //$NON-NLS-1$
+    case 940 : if (DEBUG) { System.out.println("WildcardBounds1 ::= extends ReferenceType1"); }  //$NON-NLS-1$
 		    consumeWildcardBounds1Extends();
 			break;
 
-    case 940 : if (DEBUG) { System.out.println("WildcardBounds1 ::= super ReferenceType1"); }  //$NON-NLS-1$
+    case 941 : if (DEBUG) { System.out.println("WildcardBounds1 ::= super ReferenceType1"); }  //$NON-NLS-1$
 		    consumeWildcardBounds1Super();
 			break;
 
-    case 941 : if (DEBUG) { System.out.println("Wildcard2 ::= TypeAnnotationsopt QUESTION RIGHT_SHIFT"); }  //$NON-NLS-1$
+    case 942 : if (DEBUG) { System.out.println("Wildcard2 ::= TypeAnnotationsopt QUESTION RIGHT_SHIFT"); }  //$NON-NLS-1$
 		    consumeWildcard2();
 			break;
 
-    case 942 : if (DEBUG) { System.out.println("Wildcard2 ::= TypeAnnotationsopt QUESTION..."); }  //$NON-NLS-1$
+    case 943 : if (DEBUG) { System.out.println("Wildcard2 ::= TypeAnnotationsopt QUESTION..."); }  //$NON-NLS-1$
 		    consumeWildcard2WithBounds();
 			break;
 
-    case 943 : if (DEBUG) { System.out.println("WildcardBounds2 ::= extends ReferenceType2"); }  //$NON-NLS-1$
+    case 944 : if (DEBUG) { System.out.println("WildcardBounds2 ::= extends ReferenceType2"); }  //$NON-NLS-1$
 		    consumeWildcardBounds2Extends();
 			break;
 
-    case 944 : if (DEBUG) { System.out.println("WildcardBounds2 ::= super ReferenceType2"); }  //$NON-NLS-1$
+    case 945 : if (DEBUG) { System.out.println("WildcardBounds2 ::= super ReferenceType2"); }  //$NON-NLS-1$
 		    consumeWildcardBounds2Super();
 			break;
 
-    case 945 : if (DEBUG) { System.out.println("Wildcard3 ::= TypeAnnotationsopt QUESTION..."); }  //$NON-NLS-1$
+    case 946 : if (DEBUG) { System.out.println("Wildcard3 ::= TypeAnnotationsopt QUESTION..."); }  //$NON-NLS-1$
 		    consumeWildcard3();
 			break;
 
-    case 946 : if (DEBUG) { System.out.println("Wildcard3 ::= TypeAnnotationsopt QUESTION..."); }  //$NON-NLS-1$
+    case 947 : if (DEBUG) { System.out.println("Wildcard3 ::= TypeAnnotationsopt QUESTION..."); }  //$NON-NLS-1$
 		    consumeWildcard3WithBounds();
 			break;
 
-    case 947 : if (DEBUG) { System.out.println("WildcardBounds3 ::= extends ReferenceType3"); }  //$NON-NLS-1$
+    case 948 : if (DEBUG) { System.out.println("WildcardBounds3 ::= extends ReferenceType3"); }  //$NON-NLS-1$
 		    consumeWildcardBounds3Extends();
 			break;
 
-    case 948 : if (DEBUG) { System.out.println("WildcardBounds3 ::= super ReferenceType3"); }  //$NON-NLS-1$
+    case 949 : if (DEBUG) { System.out.println("WildcardBounds3 ::= super ReferenceType3"); }  //$NON-NLS-1$
 		    consumeWildcardBounds3Super();
 			break;
 
-    case 949 : if (DEBUG) { System.out.println("TypeParameterHeader ::= TypeAnnotationsopt Identifier"); }  //$NON-NLS-1$
+    case 950 : if (DEBUG) { System.out.println("TypeParameterHeader ::= TypeAnnotationsopt Identifier"); }  //$NON-NLS-1$
 		    consumeTypeParameterHeader();
 			break;
 
-    case 950 : if (DEBUG) { System.out.println("TypeParameters ::= LESS TypeParameterList1"); }  //$NON-NLS-1$
+    case 951 : if (DEBUG) { System.out.println("TypeParameters ::= LESS TypeParameterList1"); }  //$NON-NLS-1$
 		    consumeTypeParameters();
 			break;
 
-    case 952 : if (DEBUG) { System.out.println("TypeParameterList ::= TypeParameterList COMMA..."); }  //$NON-NLS-1$
+    case 953 : if (DEBUG) { System.out.println("TypeParameterList ::= TypeParameterList COMMA..."); }  //$NON-NLS-1$
 		    consumeTypeParameterList();
 			break;
 
-    case 954 : if (DEBUG) { System.out.println("TypeParameter ::= TypeParameterHeader extends..."); }  //$NON-NLS-1$
+    case 955 : if (DEBUG) { System.out.println("TypeParameter ::= TypeParameterHeader extends..."); }  //$NON-NLS-1$
 		    consumeTypeParameterWithExtends();
 			break;
 
-    case 955 : if (DEBUG) { System.out.println("TypeParameter ::= TypeParameterHeader extends..."); }  //$NON-NLS-1$
+    case 956 : if (DEBUG) { System.out.println("TypeParameter ::= TypeParameterHeader extends..."); }  //$NON-NLS-1$
 		    consumeTypeParameterWithExtendsAndBounds();
 			break;
 
-    case 956 : if (DEBUG) { System.out.println("TypeParameter ::= TypeParameterHeader base ReferenceType"); }  //$NON-NLS-1$
+    case 957 : if (DEBUG) { System.out.println("TypeParameter ::= TypeParameterHeader base ReferenceType"); }  //$NON-NLS-1$
 		    consumeTypeParameterWithBase();
 			break;
 
-    case 960 : if (DEBUG) { System.out.println("TypeValueParameter ::= TypeParameterHeader Identifier"); }  //$NON-NLS-1$
+    case 961 : if (DEBUG) { System.out.println("TypeValueParameter ::= TypeParameterHeader Identifier"); }  //$NON-NLS-1$
 		    consumeTypeValueParameter();
 			break;
 
-    case 965 : if (DEBUG) { System.out.println("TypeBoundOpt ::= extends ReferenceType"); }  //$NON-NLS-1$
+    case 966 : if (DEBUG) { System.out.println("TypeBoundOpt ::= extends ReferenceType"); }  //$NON-NLS-1$
 		    consumeBoundsOfAnchoredTypeParameter();
 			break;
 
-    case 967 : if (DEBUG) { System.out.println("TypeBoundOpt1 ::= extends ReferenceType1"); }  //$NON-NLS-1$
+    case 968 : if (DEBUG) { System.out.println("TypeBoundOpt1 ::= extends ReferenceType1"); }  //$NON-NLS-1$
 		    consumeBoundsOfAnchoredTypeParameter();
 			break;
 
-    case 968 : if (DEBUG) { System.out.println("AnchoredTypeParameterHeader0 ::= TypeParameterHeader..."); }  //$NON-NLS-1$
+    case 969 : if (DEBUG) { System.out.println("AnchoredTypeParameterHeader0 ::= TypeParameterHeader..."); }  //$NON-NLS-1$
 		    consumeAnchoredTypeParameter();
 			break;
 
-    case 970 : if (DEBUG) { System.out.println("AdditionalBoundList ::= AdditionalBoundList..."); }  //$NON-NLS-1$
+    case 971 : if (DEBUG) { System.out.println("AdditionalBoundList ::= AdditionalBoundList..."); }  //$NON-NLS-1$
 		    consumeAdditionalBoundList();
 			break;
 
-    case 971 : if (DEBUG) { System.out.println("AdditionalBound ::= AND ReferenceType"); }  //$NON-NLS-1$
+    case 972 : if (DEBUG) { System.out.println("AdditionalBound ::= AND ReferenceType"); }  //$NON-NLS-1$
 		    consumeAdditionalBound();
 			break;
 
-    case 973 : if (DEBUG) { System.out.println("TypeParameterList1 ::= TypeParameterList COMMA..."); }  //$NON-NLS-1$
+    case 974 : if (DEBUG) { System.out.println("TypeParameterList1 ::= TypeParameterList COMMA..."); }  //$NON-NLS-1$
 		    consumeTypeParameterList1();
 			break;
 
-    case 974 : if (DEBUG) { System.out.println("TypeParameter1 ::= TypeParameterHeader GREATER"); }  //$NON-NLS-1$
+    case 975 : if (DEBUG) { System.out.println("TypeParameter1 ::= TypeParameterHeader GREATER"); }  //$NON-NLS-1$
 		    consumeTypeParameter1();
 			break;
 
-    case 975 : if (DEBUG) { System.out.println("TypeParameter1 ::= TypeParameterHeader extends..."); }  //$NON-NLS-1$
+    case 976 : if (DEBUG) { System.out.println("TypeParameter1 ::= TypeParameterHeader extends..."); }  //$NON-NLS-1$
 		    consumeTypeParameter1WithExtends();
 			break;
 
-    case 976 : if (DEBUG) { System.out.println("TypeParameter1 ::= TypeParameterHeader base..."); }  //$NON-NLS-1$
+    case 977 : if (DEBUG) { System.out.println("TypeParameter1 ::= TypeParameterHeader base..."); }  //$NON-NLS-1$
 		    consumeTypeParameter1WithBase();
 			break;
 
-    case 977 : if (DEBUG) { System.out.println("TypeParameter1 ::= TypeParameterHeader extends..."); }  //$NON-NLS-1$
+    case 978 : if (DEBUG) { System.out.println("TypeParameter1 ::= TypeParameterHeader extends..."); }  //$NON-NLS-1$
 		    consumeTypeParameter1WithExtendsAndBounds();
 			break;
 
-    case 979 : if (DEBUG) { System.out.println("AdditionalBoundList1 ::= AdditionalBoundList..."); }  //$NON-NLS-1$
+    case 980 : if (DEBUG) { System.out.println("AdditionalBoundList1 ::= AdditionalBoundList..."); }  //$NON-NLS-1$
 		    consumeAdditionalBoundList1();
 			break;
 
-    case 980 : if (DEBUG) { System.out.println("AdditionalBound1 ::= AND ReferenceType1"); }  //$NON-NLS-1$
+    case 981 : if (DEBUG) { System.out.println("AdditionalBound1 ::= AND ReferenceType1"); }  //$NON-NLS-1$
 		    consumeAdditionalBound1();
 			break;
 
-    case 986 : if (DEBUG) { System.out.println("UnaryExpression_NotName ::= PLUS PushPosition..."); }  //$NON-NLS-1$
+    case 987 : if (DEBUG) { System.out.println("UnaryExpression_NotName ::= PLUS PushPosition..."); }  //$NON-NLS-1$
 		    consumeUnaryExpression(OperatorIds.PLUS);
 			break;
 
-    case 987 : if (DEBUG) { System.out.println("UnaryExpression_NotName ::= MINUS PushPosition..."); }  //$NON-NLS-1$
+    case 988 : if (DEBUG) { System.out.println("UnaryExpression_NotName ::= MINUS PushPosition..."); }  //$NON-NLS-1$
 		    consumeUnaryExpression(OperatorIds.MINUS);
 			break;
 
-    case 990 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus_NotName ::= TWIDDLE..."); }  //$NON-NLS-1$
+    case 991 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus_NotName ::= TWIDDLE..."); }  //$NON-NLS-1$
 		    consumeUnaryExpression(OperatorIds.TWIDDLE);
 			break;
 
-    case 991 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus_NotName ::= NOT PushPosition"); }  //$NON-NLS-1$
+    case 992 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus_NotName ::= NOT PushPosition"); }  //$NON-NLS-1$
 		    consumeUnaryExpression(OperatorIds.NOT);
 			break;
 
-    case 994 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 995 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.MULTIPLY);
 			break;
 
-    case 995 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::= Name MULTIPLY..."); }  //$NON-NLS-1$
+    case 996 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::= Name MULTIPLY..."); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.MULTIPLY);
 			break;
 
-    case 996 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 997 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.DIVIDE);
 			break;
 
-    case 997 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::= Name DIVIDE..."); }  //$NON-NLS-1$
+    case 998 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::= Name DIVIDE..."); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.DIVIDE);
 			break;
 
-    case 998 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 999 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.REMAINDER);
 			break;
 
-    case 999 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::= Name REMAINDER..."); }  //$NON-NLS-1$
+    case 1000 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::= Name REMAINDER..."); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.REMAINDER);
 			break;
 
-    case 1001 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 1002 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.PLUS);
 			break;
 
-    case 1002 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::= Name PLUS..."); }  //$NON-NLS-1$
+    case 1003 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::= Name PLUS..."); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.PLUS);
 			break;
 
-    case 1003 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 1004 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.MINUS);
 			break;
 
-    case 1004 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::= Name MINUS..."); }  //$NON-NLS-1$
+    case 1005 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::= Name MINUS..."); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.MINUS);
 			break;
 
-    case 1006 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= ShiftExpression_NotName..."); }  //$NON-NLS-1$
+    case 1007 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= ShiftExpression_NotName..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.LEFT_SHIFT);
 			break;
 
-    case 1007 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= Name LEFT_SHIFT..."); }  //$NON-NLS-1$
+    case 1008 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= Name LEFT_SHIFT..."); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.LEFT_SHIFT);
 			break;
 
-    case 1008 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= ShiftExpression_NotName..."); }  //$NON-NLS-1$
+    case 1009 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= ShiftExpression_NotName..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.RIGHT_SHIFT);
 			break;
 
-    case 1009 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= Name RIGHT_SHIFT..."); }  //$NON-NLS-1$
+    case 1010 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= Name RIGHT_SHIFT..."); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.RIGHT_SHIFT);
 			break;
 
-    case 1010 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= ShiftExpression_NotName..."); }  //$NON-NLS-1$
+    case 1011 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= ShiftExpression_NotName..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.UNSIGNED_RIGHT_SHIFT);
 			break;
 
-    case 1011 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= Name UNSIGNED_RIGHT_SHIFT"); }  //$NON-NLS-1$
+    case 1012 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= Name UNSIGNED_RIGHT_SHIFT"); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.UNSIGNED_RIGHT_SHIFT);
 			break;
 
-    case 1013 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 1014 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.LESS);
 			break;
 
-    case 1014 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name LESS..."); }  //$NON-NLS-1$
+    case 1015 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name LESS..."); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.LESS);
 			break;
 
-    case 1015 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 1016 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.GREATER);
 			break;
 
-    case 1016 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name GREATER..."); }  //$NON-NLS-1$
+    case 1017 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name GREATER..."); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.GREATER);
 			break;
 
-    case 1017 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 1018 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.LESS_EQUAL);
 			break;
 
-    case 1018 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name LESS_EQUAL..."); }  //$NON-NLS-1$
+    case 1019 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name LESS_EQUAL..."); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.LESS_EQUAL);
 			break;
 
-    case 1019 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 1020 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.GREATER_EQUAL);
 			break;
 
-    case 1020 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name GREATER_EQUAL..."); }  //$NON-NLS-1$
+    case 1021 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name GREATER_EQUAL..."); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.GREATER_EQUAL);
 			break;
 
-    case 1022 : if (DEBUG) { System.out.println("InstanceofExpression_NotName ::= Name InstanceofRHS"); }  //$NON-NLS-1$
+    case 1023 : if (DEBUG) { System.out.println("InstanceofExpression_NotName ::= Name InstanceofRHS"); }  //$NON-NLS-1$
 		    consumeInstanceOfExpressionWithName();
 			break;
 
-    case 1023 : if (DEBUG) { System.out.println("InstanceofExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 1024 : if (DEBUG) { System.out.println("InstanceofExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeInstanceOfExpression();
 			break;
 
-    case 1025 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 1026 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeEqualityExpression(OperatorIds.EQUAL_EQUAL);
 			break;
 
-    case 1026 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::= Name EQUAL_EQUAL..."); }  //$NON-NLS-1$
+    case 1027 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::= Name EQUAL_EQUAL..."); }  //$NON-NLS-1$
 		    consumeEqualityExpressionWithName(OperatorIds.EQUAL_EQUAL);
 			break;
 
-    case 1027 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 1028 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeEqualityExpression(OperatorIds.NOT_EQUAL);
 			break;
 
-    case 1028 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::= Name NOT_EQUAL..."); }  //$NON-NLS-1$
+    case 1029 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::= Name NOT_EQUAL..."); }  //$NON-NLS-1$
 		    consumeEqualityExpressionWithName(OperatorIds.NOT_EQUAL);
 			break;
 
-    case 1030 : if (DEBUG) { System.out.println("AndExpression_NotName ::= AndExpression_NotName AND..."); }  //$NON-NLS-1$
+    case 1031 : if (DEBUG) { System.out.println("AndExpression_NotName ::= AndExpression_NotName AND..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.AND);
 			break;
 
-    case 1031 : if (DEBUG) { System.out.println("AndExpression_NotName ::= Name AND EqualityExpression"); }  //$NON-NLS-1$
+    case 1032 : if (DEBUG) { System.out.println("AndExpression_NotName ::= Name AND EqualityExpression"); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.AND);
 			break;
 
-    case 1033 : if (DEBUG) { System.out.println("ExclusiveOrExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 1034 : if (DEBUG) { System.out.println("ExclusiveOrExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.XOR);
 			break;
 
-    case 1034 : if (DEBUG) { System.out.println("ExclusiveOrExpression_NotName ::= Name XOR..."); }  //$NON-NLS-1$
+    case 1035 : if (DEBUG) { System.out.println("ExclusiveOrExpression_NotName ::= Name XOR..."); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.XOR);
 			break;
 
-    case 1036 : if (DEBUG) { System.out.println("InclusiveOrExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 1037 : if (DEBUG) { System.out.println("InclusiveOrExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.OR);
 			break;
 
-    case 1037 : if (DEBUG) { System.out.println("InclusiveOrExpression_NotName ::= Name OR..."); }  //$NON-NLS-1$
+    case 1038 : if (DEBUG) { System.out.println("InclusiveOrExpression_NotName ::= Name OR..."); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.OR);
 			break;
 
-    case 1039 : if (DEBUG) { System.out.println("ConditionalAndExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 1040 : if (DEBUG) { System.out.println("ConditionalAndExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.AND_AND);
 			break;
 
-    case 1040 : if (DEBUG) { System.out.println("ConditionalAndExpression_NotName ::= Name AND_AND..."); }  //$NON-NLS-1$
+    case 1041 : if (DEBUG) { System.out.println("ConditionalAndExpression_NotName ::= Name AND_AND..."); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.AND_AND);
 			break;
 
-    case 1042 : if (DEBUG) { System.out.println("ConditionalOrExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 1043 : if (DEBUG) { System.out.println("ConditionalOrExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.OR_OR);
 			break;
 
-    case 1043 : if (DEBUG) { System.out.println("ConditionalOrExpression_NotName ::= Name OR_OR..."); }  //$NON-NLS-1$
+    case 1044 : if (DEBUG) { System.out.println("ConditionalOrExpression_NotName ::= Name OR_OR..."); }  //$NON-NLS-1$
 		    consumeBinaryExpressionWithName(OperatorIds.OR_OR);
 			break;
 
-    case 1045 : if (DEBUG) { System.out.println("ConditionalExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 1046 : if (DEBUG) { System.out.println("ConditionalExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeConditionalExpression(OperatorIds.QUESTIONCOLON) ;
 			break;
 
-    case 1046 : if (DEBUG) { System.out.println("ConditionalExpression_NotName ::= Name QUESTION..."); }  //$NON-NLS-1$
+    case 1047 : if (DEBUG) { System.out.println("ConditionalExpression_NotName ::= Name QUESTION..."); }  //$NON-NLS-1$
 		    consumeConditionalExpressionWithName(OperatorIds.QUESTIONCOLON) ;
 			break;
 
-    case 1050 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= Modifiers AT..."); }  //$NON-NLS-1$
+    case 1051 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= Modifiers AT..."); }  //$NON-NLS-1$
 		    consumeAnnotationTypeDeclarationHeaderName() ;
 			break;
 
-    case 1051 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= Modifiers AT..."); }  //$NON-NLS-1$
-		    consumeAnnotationTypeDeclarationHeaderNameWithTypeParameters() ;
-			break;
-
-    case 1052 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= AT..."); }  //$NON-NLS-1$
+    case 1052 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= Modifiers AT..."); }  //$NON-NLS-1$
 		    consumeAnnotationTypeDeclarationHeaderNameWithTypeParameters() ;
 			break;
 
     case 1053 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= AT..."); }  //$NON-NLS-1$
+		    consumeAnnotationTypeDeclarationHeaderNameWithTypeParameters() ;
+			break;
+
+    case 1054 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= AT..."); }  //$NON-NLS-1$
 		    consumeAnnotationTypeDeclarationHeaderName() ;
 			break;
 
-    case 1054 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeader ::=..."); }  //$NON-NLS-1$
+    case 1055 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeader ::=..."); }  //$NON-NLS-1$
 		    consumeAnnotationTypeDeclarationHeader() ;
 			break;
 
-    case 1055 : if (DEBUG) { System.out.println("AnnotationTypeDeclaration ::=..."); }  //$NON-NLS-1$
+    case 1056 : if (DEBUG) { System.out.println("AnnotationTypeDeclaration ::=..."); }  //$NON-NLS-1$
 		    consumeAnnotationTypeDeclaration() ;
 			break;
 
-    case 1057 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclarationsopt ::="); }  //$NON-NLS-1$
+    case 1058 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclarationsopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyAnnotationTypeMemberDeclarationsopt() ;
 			break;
 
-    case 1058 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclarationsopt ::= NestedType..."); }  //$NON-NLS-1$
+    case 1059 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclarationsopt ::= NestedType..."); }  //$NON-NLS-1$
 		    consumeAnnotationTypeMemberDeclarationsopt() ;
 			break;
 
-    case 1060 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclarations ::=..."); }  //$NON-NLS-1$
+    case 1061 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclarations ::=..."); }  //$NON-NLS-1$
 		    consumeAnnotationTypeMemberDeclarations() ;
 			break;
 
-    case 1061 : if (DEBUG) { System.out.println("AnnotationMethodHeaderName ::= Modifiersopt..."); }  //$NON-NLS-1$
+    case 1062 : if (DEBUG) { System.out.println("AnnotationMethodHeaderName ::= Modifiersopt..."); }  //$NON-NLS-1$
 		    consumeMethodHeaderNameWithTypeParameters(true);
 			break;
 
-    case 1062 : if (DEBUG) { System.out.println("AnnotationMethodHeaderName ::= Modifiersopt Type..."); }  //$NON-NLS-1$
+    case 1063 : if (DEBUG) { System.out.println("AnnotationMethodHeaderName ::= Modifiersopt Type..."); }  //$NON-NLS-1$
 		    consumeMethodHeaderName(true);
 			break;
 
-    case 1063 : if (DEBUG) { System.out.println("AnnotationMethodHeaderDefaultValueopt ::="); }  //$NON-NLS-1$
+    case 1064 : if (DEBUG) { System.out.println("AnnotationMethodHeaderDefaultValueopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyMethodHeaderDefaultValue() ;
 			break;
 
-    case 1064 : if (DEBUG) { System.out.println("AnnotationMethodHeaderDefaultValueopt ::= DefaultValue"); }  //$NON-NLS-1$
+    case 1065 : if (DEBUG) { System.out.println("AnnotationMethodHeaderDefaultValueopt ::= DefaultValue"); }  //$NON-NLS-1$
 		    consumeMethodHeaderDefaultValue();
 			break;
 
-    case 1065 : if (DEBUG) { System.out.println("AnnotationMethodHeader ::= AnnotationMethodHeaderName"); }  //$NON-NLS-1$
+    case 1066 : if (DEBUG) { System.out.println("AnnotationMethodHeader ::= AnnotationMethodHeaderName"); }  //$NON-NLS-1$
 		    consumeMethodHeader();
 			break;
 
-    case 1066 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclaration ::=..."); }  //$NON-NLS-1$
+    case 1067 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclaration ::=..."); }  //$NON-NLS-1$
 		    consumeAnnotationTypeMemberDeclaration() ;
 			break;
 
-    case 1074 : if (DEBUG) { System.out.println("AnnotationName ::= AT UnannotatableName"); }  //$NON-NLS-1$
+    case 1075 : if (DEBUG) { System.out.println("AnnotationName ::= AT UnannotatableName"); }  //$NON-NLS-1$
 		    consumeAnnotationName() ;
 			break;
 
-    case 1075 : if (DEBUG) { System.out.println("NormalAnnotation ::= AnnotationName LPAREN..."); }  //$NON-NLS-1$
+    case 1076 : if (DEBUG) { System.out.println("NormalAnnotation ::= AnnotationName LPAREN..."); }  //$NON-NLS-1$
 		    consumeNormalAnnotation(false) ;
 			break;
 
-    case 1076 : if (DEBUG) { System.out.println("MemberValuePairsopt ::="); }  //$NON-NLS-1$
+    case 1077 : if (DEBUG) { System.out.println("MemberValuePairsopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyMemberValuePairsopt() ;
 			break;
 
-    case 1079 : if (DEBUG) { System.out.println("MemberValuePairs ::= MemberValuePairs COMMA..."); }  //$NON-NLS-1$
+    case 1080 : if (DEBUG) { System.out.println("MemberValuePairs ::= MemberValuePairs COMMA..."); }  //$NON-NLS-1$
 		    consumeMemberValuePairs() ;
 			break;
 
-    case 1080 : if (DEBUG) { System.out.println("MemberValuePair ::= SimpleName EQUAL EnterMemberValue"); }  //$NON-NLS-1$
+    case 1081 : if (DEBUG) { System.out.println("MemberValuePair ::= SimpleName EQUAL EnterMemberValue"); }  //$NON-NLS-1$
 		    consumeMemberValuePair() ;
 			break;
 
-    case 1081 : if (DEBUG) { System.out.println("EnterMemberValue ::="); }  //$NON-NLS-1$
+    case 1082 : if (DEBUG) { System.out.println("EnterMemberValue ::="); }  //$NON-NLS-1$
 		    consumeEnterMemberValue() ;
 			break;
 
-    case 1082 : if (DEBUG) { System.out.println("ExitMemberValue ::="); }  //$NON-NLS-1$
+    case 1083 : if (DEBUG) { System.out.println("ExitMemberValue ::="); }  //$NON-NLS-1$
 		    consumeExitMemberValue() ;
 			break;
 
-    case 1084 : if (DEBUG) { System.out.println("MemberValue ::= Name"); }  //$NON-NLS-1$
+    case 1085 : if (DEBUG) { System.out.println("MemberValue ::= Name"); }  //$NON-NLS-1$
 		    consumeMemberValueAsName() ;
 			break;
 
-    case 1087 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::=..."); }  //$NON-NLS-1$
-		    consumeMemberValueArrayInitializer() ;
-			break;
-
     case 1088 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::=..."); }  //$NON-NLS-1$
 		    consumeMemberValueArrayInitializer() ;
 			break;
 
     case 1089 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::=..."); }  //$NON-NLS-1$
-		    consumeEmptyMemberValueArrayInitializer() ;
+		    consumeMemberValueArrayInitializer() ;
 			break;
 
     case 1090 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::=..."); }  //$NON-NLS-1$
 		    consumeEmptyMemberValueArrayInitializer() ;
 			break;
 
-    case 1091 : if (DEBUG) { System.out.println("EnterMemberValueArrayInitializer ::="); }  //$NON-NLS-1$
+    case 1091 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::=..."); }  //$NON-NLS-1$
+		    consumeEmptyMemberValueArrayInitializer() ;
+			break;
+
+    case 1092 : if (DEBUG) { System.out.println("EnterMemberValueArrayInitializer ::="); }  //$NON-NLS-1$
 		    consumeEnterMemberValueArrayInitializer() ;
 			break;
 
-    case 1093 : if (DEBUG) { System.out.println("MemberValues ::= MemberValues COMMA MemberValue"); }  //$NON-NLS-1$
+    case 1094 : if (DEBUG) { System.out.println("MemberValues ::= MemberValues COMMA MemberValue"); }  //$NON-NLS-1$
 		    consumeMemberValues() ;
 			break;
 
-    case 1094 : if (DEBUG) { System.out.println("MarkerAnnotation ::= AnnotationName"); }  //$NON-NLS-1$
+    case 1095 : if (DEBUG) { System.out.println("MarkerAnnotation ::= AnnotationName"); }  //$NON-NLS-1$
 		    consumeMarkerAnnotation(false) ;
 			break;
 
-    case 1095 : if (DEBUG) { System.out.println("SingleMemberAnnotationMemberValue ::= MemberValue"); }  //$NON-NLS-1$
+    case 1096 : if (DEBUG) { System.out.println("SingleMemberAnnotationMemberValue ::= MemberValue"); }  //$NON-NLS-1$
 		    consumeSingleMemberAnnotationMemberValue() ;
 			break;
 
-    case 1096 : if (DEBUG) { System.out.println("SingleMemberAnnotation ::= AnnotationName LPAREN..."); }  //$NON-NLS-1$
+    case 1097 : if (DEBUG) { System.out.println("SingleMemberAnnotation ::= AnnotationName LPAREN..."); }  //$NON-NLS-1$
 		    consumeSingleMemberAnnotation(false) ;
 			break;
 
-    case 1097 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= Modifiersopt..."); }  //$NON-NLS-1$
+    case 1098 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= Modifiersopt..."); }  //$NON-NLS-1$
 		    consumeRecoveryMethodHeaderNameWithTypeParameters();
 			break;
 
-    case 1098 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= Modifiersopt Type..."); }  //$NON-NLS-1$
+    case 1099 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= Modifiersopt Type..."); }  //$NON-NLS-1$
 		    consumeRecoveryMethodHeaderName();
 			break;
 
-    case 1099 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= ModifiersWithDefault..."); }  //$NON-NLS-1$
+    case 1100 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= ModifiersWithDefault..."); }  //$NON-NLS-1$
 		    consumeRecoveryMethodHeaderNameWithTypeParameters();
 			break;
 
-    case 1100 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= ModifiersWithDefault Type"); }  //$NON-NLS-1$
+    case 1101 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= ModifiersWithDefault Type"); }  //$NON-NLS-1$
 		    consumeRecoveryMethodHeaderName();
 			break;
 
-    case 1101 : if (DEBUG) { System.out.println("RecoveryMethodHeader ::= RecoveryMethodHeaderName..."); }  //$NON-NLS-1$
-		    consumeMethodHeader();
-			break;
-
     case 1102 : if (DEBUG) { System.out.println("RecoveryMethodHeader ::= RecoveryMethodHeaderName..."); }  //$NON-NLS-1$
 		    consumeMethodHeader();
 			break;
 
-    case 1105 : if (DEBUG) { System.out.println("RecoveryCallinHeader ::= RecoveryCallinBindingLeftLong"); }  //$NON-NLS-1$
+    case 1103 : if (DEBUG) { System.out.println("RecoveryMethodHeader ::= RecoveryMethodHeaderName..."); }  //$NON-NLS-1$
+		    consumeMethodHeader();
+			break;
+
+    case 1106 : if (DEBUG) { System.out.println("RecoveryCallinHeader ::= RecoveryCallinBindingLeftLong"); }  //$NON-NLS-1$
 		    consumeCallinHeader();
 			break;
 
-    case 1106 : if (DEBUG) { System.out.println("RecoveryCallinHeader ::= Modifiersopt CallinLabel..."); }  //$NON-NLS-1$
+    case 1107 : if (DEBUG) { System.out.println("RecoveryCallinHeader ::= Modifiersopt CallinLabel..."); }  //$NON-NLS-1$
 		    consumeCallinHeader();
 			break;
 
-    case 1107 : if (DEBUG) { System.out.println("RecoveryCallinBindingLeftLong ::=..."); }  //$NON-NLS-1$
+    case 1108 : if (DEBUG) { System.out.println("RecoveryCallinBindingLeftLong ::=..."); }  //$NON-NLS-1$
 		    consumeCallinBindingLeft(true);
 			break;
 
-    case 1108 : if (DEBUG) { System.out.println("RecoveryCallinHeader ::= Modifiersopt..."); }  //$NON-NLS-1$
+    case 1109 : if (DEBUG) { System.out.println("RecoveryCallinHeader ::= Modifiersopt..."); }  //$NON-NLS-1$
 		    consumeCallinHeader();
 			break;
 
-    case 1109 : if (DEBUG) { System.out.println("RecoveryCallinHeader ::= Modifiersopt CallinLabel..."); }  //$NON-NLS-1$
+    case 1110 : if (DEBUG) { System.out.println("RecoveryCallinHeader ::= Modifiersopt CallinLabel..."); }  //$NON-NLS-1$
 		    consumeCallinHeader();
 			break;
 
-    case 1110 : if (DEBUG) { System.out.println("RecoveryCalloutHeader ::=..."); }  //$NON-NLS-1$
+    case 1111 : if (DEBUG) { System.out.println("RecoveryCalloutHeader ::=..."); }  //$NON-NLS-1$
 		    consumeCalloutHeader();
 			break;
 
-    case 1111 : if (DEBUG) { System.out.println("RecoveryCalloutBindingLeftLong ::=..."); }  //$NON-NLS-1$
+    case 1112 : if (DEBUG) { System.out.println("RecoveryCalloutBindingLeftLong ::=..."); }  //$NON-NLS-1$
 		    consumeCalloutBindingLeft(true);
 			break;
 
-    case 1112 : if (DEBUG) { System.out.println("RecoveryCalloutHeader ::=..."); }  //$NON-NLS-1$
+    case 1113 : if (DEBUG) { System.out.println("RecoveryCalloutHeader ::=..."); }  //$NON-NLS-1$
 		    consumeCalloutHeader();
 			break;
 
-    case 1113 : if (DEBUG) { System.out.println("RecoveryCalloutHeader ::= Modifiersopt..."); }  //$NON-NLS-1$
+    case 1114 : if (DEBUG) { System.out.println("RecoveryCalloutHeader ::= Modifiersopt..."); }  //$NON-NLS-1$
 		    consumeCalloutHeader();
 			break;
 
-    case 1114 : if (DEBUG) { System.out.println("RecoveryMethodSpecLong ::= RecoveryMethodHeaderName..."); }  //$NON-NLS-1$
+    case 1115 : if (DEBUG) { System.out.println("RecoveryMethodSpecLong ::= RecoveryMethodHeaderName..."); }  //$NON-NLS-1$
 		    consumeMethodSpecLong(false);
 			break;
 
@@ -12075,7 +12108,8 @@
 	if (length == 0 && !containsComment(switchStatement.blockStart, switchStatement.sourceEnd)) {
 		switchStatement.bits |= ASTNode.UndocumentedEmptyBlock;
 	}
-	this.scanner.caseStartPosition = -1; // safety: at the end of a switch we definitely leave the scope of this value
+//	this.scanner.caseStartPosition = -1; // safety: at the end of a switch we definitely leave the scope of this value
+	this.scanner.caseStartPosition =  resetCaseStartAndPopPrev(this.switchNestingLevel + 1); // +1 because already dec above
 	return switchStatement;
 }
 protected void consumeStatementSwitch() {
@@ -12319,7 +12353,11 @@
 protected void consumeSwitchLabelCaseLhs() {
 	if (this.scanner.lookBack[1] == TerminalTokens.TokenNameCOLON) // kludge for yield :(
 		this.scanner.yieldColons = 1;
-	this.scanner.caseStartPosition = -1; // value has expired
+	if (this.switchNestingLevel >= 0) {
+		this.caseStartMap.put(this.switchNestingLevel, -1);
+	}
+	this.scanner.caseStartPosition =  resetCaseStartAndPopPrev(this.switchNestingLevel);
+
 }
 protected void consumeCaseLabelExpr() {
 //	SwitchLabelExpr ::= SwitchLabelCaseLhs BeginCaseExpr '->'
@@ -12850,9 +12888,8 @@
 			pushOnIntStack(this.scanner.startPosition);
 			break;
 		case TokenNamecase :
-			this.caseLevel = this.switchNestingLevel;
 			pushOnIntStack(this.scanner.startPosition);
-			pushOnCaseStack(this.scanner.startPosition);
+			this.caseStartMap.put(this.switchNestingLevel, this.scanner.startPosition);
 			break;
 		case TokenNameswitch :
 			consumeNestedType();
@@ -13482,7 +13519,13 @@
 	Pattern pattern = (Pattern) this.astStack[this.astPtr--];
 	Expression expr = this.expressionStack[this.expressionPtr--];
 	this.expressionLengthPtr--;
-	pushOnAstStack(new GuardedPattern(pattern, expr));
+	if (pattern instanceof GuardedPattern) {
+		GuardedPattern gPattern = (GuardedPattern) pattern;
+		AND_AND_Expression andExpression = new AND_AND_Expression(gPattern.condition, expr, OperatorIds.AND_AND);
+		pushOnAstStack(new GuardedPattern(gPattern.primaryPattern, andExpression));
+	} else {
+		pushOnAstStack(new GuardedPattern(pattern, expr));
+	}
 }
 protected void consumeTypePattern() {
 
@@ -15363,9 +15406,9 @@
 	this.identifierPtr = -1;
 	this.identifierLengthPtr	= -1;
 	this.intPtr = -1;
-	this.casePtr = -1;
 	this.nestedMethod[this.nestedType = 0] = 0; // need to reset for further reuse
 	this.switchNestingLevel = 0;
+	this.caseStartMap.clear();
 	this.switchWithTry = false;
 	this.variablesCounter[this.nestedType] = 0;
 	this.dimensions = 0 ;
@@ -17091,18 +17134,18 @@
 	}
 	this.intStack[this.intPtr] = pos;
 }
-protected void pushOnCaseStack(int pos) {
-
-	int stackLength = this.caseStack.length;
-	if (++this.casePtr >= stackLength) {
-		System.arraycopy(
-			this.caseStack, 0,
-			this.caseStack = new int[stackLength + StackIncrement], 0,
-			stackLength);
-	}
-	this.caseStack[this.casePtr] = pos;
-	// this.scanner.caseStartPosition updated at the scanner anyway - so not updating again.
-}
+//protected void _pushOnCaseStack(int pos) {
+//
+//	int stackLength = this.caseStartMap.length;
+//	if (++this.casePtr >= stackLength) {
+//		System.arraycopy(
+//			this.caseStartMap, 0,
+//			this.caseStartMap = new int[stackLength + StackIncrement], 0,
+//			stackLength);
+//	}
+//	this.caseStartMap[this.casePtr] = pos;
+//	// this.scanner.caseStartPosition updated at the scanner anyway - so not updating again.
+//}
 protected void pushOnRealBlockStack(int i){
 
 	int stackLength = this.realBlockStack.length;
@@ -17685,8 +17728,10 @@
 	if (this.lastPosistion < this.scanner.currentPosition) {
 		this.lastPosistion = this.scanner.currentPosition;
 		this.scanner.lastPosition = this.scanner.currentPosition;
-		if (this.scanner.startPosition <= this.scanner.caseStartPosition)
+		if (this.scanner.startPosition <= this.scanner.caseStartPosition) {
 			this.scanner.caseStartPosition = -1;
+		}
+
 	}
 
 	/* attempt to reset state in order to resume to parse loop */
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 814132a..66b8882 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
@@ -21,20 +21,20 @@
 
 					ERROR_SYMBOL = 154,
 					MAX_NAME_LENGTH = 53,
-					NUM_STATES = 1491,
+					NUM_STATES = 1492,
 
 					NT_OFFSET = 154,
 					SCOPE_UBOUND = 408,
 					SCOPE_SIZE = 409,
-					LA_STATE_OFFSET = 21487,
+					LA_STATE_OFFSET = 21488,
 					MAX_LA = 1,
-					NUM_RULES = 1114,
+					NUM_RULES = 1115,
 					NUM_TERMINALS = 154,
 					NUM_NON_TERMINALS = 508,
 					NUM_SYMBOLS = 662,
-					START_STATE = 1352,
+					START_STATE = 1353,
 					EOFT_SYMBOL = 69,
 					EOLT_SYMBOL = 69,
-					ACCEPT_ACTION = 21486,
-					ERROR_ACTION = 21487;
+					ACCEPT_ACTION = 21487,
+					ERROR_ACTION = 21488;
 }
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 808cb33..6ffd4e8 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
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2021 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -1584,7 +1584,7 @@
 	}
 	this.nextToken = unambiguousToken;
 }
-private void updateCase(int token) {
+protected void updateCase(int token) {
 	if (token == TokenNamecase) {
 		this.caseStartPosition = this.startPosition;
 		this.breakPreviewAllowed = true;
@@ -1611,6 +1611,7 @@
 		this.scanContext = isInModuleDeclaration() ? ScanContext.EXPECTING_KEYWORD : ScanContext.INACTIVE;
 	}
 	token = getNextToken0();
+	updateCase(token);
 	if (areRestrictedModuleKeywordsActive()) {
 		if (isRestrictedKeyword(token))
 			token = disambiguatedRestrictedKeyword(token);
@@ -1629,7 +1630,6 @@
 	this.lookBack[0] = this.lookBack[1];
 	this.lookBack[1] = token;
 	this.multiCaseLabelComma = false;
-	updateCase(token);
 	return token;
 }
 protected int getNextToken0() throws InvalidInputException {
@@ -1923,87 +1923,7 @@
 					++this.yieldColons;
 					return TokenNameCOLON;
 				case '\'' :
-					{
-						int test;
-						if ((test = getNextChar('\n', '\r')) == 0) {
-							throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
-						}
-						if (test > 0) {
-							// relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
-							for (int lookAhead = 0; lookAhead < 3; lookAhead++) {
-								if (this.currentPosition + lookAhead == this.eofPosition)
-									break;
-								if (this.source[this.currentPosition + lookAhead] == '\n')
-									break;
-								if (this.source[this.currentPosition + lookAhead] == '\'') {
-									this.currentPosition += lookAhead + 1;
-									break;
-								}
-							}
-							throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
-						}
-					}
-					if (getNextChar('\'')) {
-						// relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
-						for (int lookAhead = 0; lookAhead < 3; lookAhead++) {
-							if (this.currentPosition + lookAhead == this.eofPosition)
-								break;
-							if (this.source[this.currentPosition + lookAhead] == '\n')
-								break;
-							if (this.source[this.currentPosition + lookAhead] == '\'') {
-								this.currentPosition += lookAhead + 1;
-								break;
-							}
-						}
-						throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
-					}
-					if (getNextChar('\\')) {
-						if (this.unicodeAsBackSlash) {
-							// consume next character
-							this.unicodeAsBackSlash = false;
-							if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
-								getNextUnicodeChar();
-							} else {
-								if (this.withoutUnicodePtr != 0) {
-									unicodeStore();
-								}
-							}
-						} else {
-							this.currentCharacter = this.source[this.currentPosition++];
-						}
-						scanEscapeCharacter();
-					} else { // consume next character
-						this.unicodeAsBackSlash = false;
-						checkIfUnicode = false;
-						try {
-							checkIfUnicode = ((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
-							&& (this.source[this.currentPosition] == 'u');
-						} catch(IndexOutOfBoundsException e) {
-							this.currentPosition--;
-							throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
-						}
-						if (checkIfUnicode) {
-							getNextUnicodeChar();
-						} else {
-							if (this.withoutUnicodePtr != 0) {
-								unicodeStore();
-							}
-						}
-					}
-					if (getNextChar('\''))
-						return TokenNameCharacterLiteral;
-					// relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
-					for (int lookAhead = 0; lookAhead < 20; lookAhead++) {
-						if (this.currentPosition + lookAhead == this.eofPosition)
-							break;
-						if (this.source[this.currentPosition + lookAhead] == '\n')
-							break;
-						if (this.source[this.currentPosition + lookAhead] == '\'') {
-							this.currentPosition += lookAhead + 1;
-							break;
-						}
-					}
-					throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
+					return processSingleQuotes(checkIfUnicode);
 				case '"' :
 					return scanForStringLiteral();
 				case '/' :
@@ -2301,7 +2221,90 @@
 	}
 	return true;
 }
-private int scanForStringLiteral() throws InvalidInputException {
+protected int processSingleQuotes(boolean checkIfUnicode) throws InvalidInputException{
+	{
+		int test;
+		if ((test = getNextChar('\n', '\r')) == 0) {
+			throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
+		}
+		if (test > 0) {
+			// relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
+			for (int lookAhead = 0; lookAhead < 3; lookAhead++) {
+				if (this.currentPosition + lookAhead == this.eofPosition)
+					break;
+				if (this.source[this.currentPosition + lookAhead] == '\n')
+					break;
+				if (this.source[this.currentPosition + lookAhead] == '\'') {
+					this.currentPosition += lookAhead + 1;
+					break;
+				}
+			}
+			throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
+		}
+	}
+	if (getNextChar('\'')) {
+		// relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
+		for (int lookAhead = 0; lookAhead < 3; lookAhead++) {
+			if (this.currentPosition + lookAhead == this.eofPosition)
+				break;
+			if (this.source[this.currentPosition + lookAhead] == '\n')
+				break;
+			if (this.source[this.currentPosition + lookAhead] == '\'') {
+				this.currentPosition += lookAhead + 1;
+				break;
+			}
+		}
+		throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
+	}
+	if (getNextChar('\\')) {
+		if (this.unicodeAsBackSlash) {
+			// consume next character
+			this.unicodeAsBackSlash = false;
+			if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
+				getNextUnicodeChar();
+			} else {
+				if (this.withoutUnicodePtr != 0) {
+					unicodeStore();
+				}
+			}
+		} else {
+			this.currentCharacter = this.source[this.currentPosition++];
+		}
+		scanEscapeCharacter();
+	} else { // consume next character
+		this.unicodeAsBackSlash = false;
+		checkIfUnicode = false;
+		try {
+			checkIfUnicode = ((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+			&& (this.source[this.currentPosition] == 'u');
+		} catch(IndexOutOfBoundsException e) {
+			this.currentPosition--;
+			throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
+		}
+		if (checkIfUnicode) {
+			getNextUnicodeChar();
+		} else {
+			if (this.withoutUnicodePtr != 0) {
+				unicodeStore();
+			}
+		}
+	}
+	if (getNextChar('\''))
+		return TokenNameCharacterLiteral;
+	// relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
+	for (int lookAhead = 0; lookAhead < 20; lookAhead++) {
+		if (this.currentPosition + lookAhead == this.eofPosition)
+			break;
+		if (this.source[this.currentPosition + lookAhead] == '\n')
+			break;
+		if (this.source[this.currentPosition + lookAhead] == '\'') {
+			this.currentPosition += lookAhead + 1;
+			break;
+		}
+	}
+	throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
+}
+protected int scanForStringLiteral() throws InvalidInputException {
 	boolean isTextBlock = false;
 
 	// consume next character
@@ -2449,6 +2452,7 @@
 					case 'r' :
 					case 'f' :
 					case 's' :
+					case 't' :
 						break outer;
 					case '\n' :
 					case '\r' :
@@ -5664,20 +5668,30 @@
 			this.scanContext = isInModuleDeclaration() ? ScanContext.EXPECTING_KEYWORD : ScanContext.INACTIVE;
 		}
 		token = getNextToken0();
+		updateCase(token);
 		if (areRestrictedModuleKeywordsActive()) {
 			if (isRestrictedKeyword(token))
 				token = disambiguatedRestrictedKeyword(token);
 			updateScanContext(token);
 		} else if (mayBeAtCasePattern(token)) {
 			token = disambiguateCasePattern(token, this);
-		} else
-		if (token == TokenNameAT && atTypeAnnotation()) {
+		} else if (token == TokenNameARROW  &&
+				mayBeAtCaseLabelExpr() &&  this.caseStartPosition < this.startPosition) {
+				// this.caseStartPosition > this.startPositionpossible on recovery - bother only about correct ones.
+				// add fake token of TokenNameCOLON, call vanguard on this modified source
+				// TODO: Inefficient method due to redoing of the same source, investigate alternate
+				// Can we do a dup of parsing/check the transition of the state?
+				token = disambiguateArrowWithCaseExpr(this, token);
+		} else	if (token == TokenNameAT && atTypeAnnotation()) {
 			if (((VanguardParser) this.activeParser).currentGoal == Goal.LambdaParameterListGoal) {
 				token = disambiguatedToken(token, this);
 			} else {
 				token = TokenNameAT308;
 			}
 		}
+		this.lookBack[0] = this.lookBack[1];
+		this.lookBack[1] = token;
+		this.multiCaseLabelComma = false;
 		return token == TokenNameEOF ? TokenNameNotAToken : token;
 	}
 }
@@ -5713,7 +5727,7 @@
 	static int[] RestrictedIdentifierSealedFollow =  { TokenNameclass, TokenNameinterface,
 			TokenNameenum, TokenNameRestrictedIdentifierrecord };// Note: enum/record allowed as error flagging rules.
 	static int[] RestrictedIdentifierPermitsFollow =  { TokenNameLBRACE };
-	static int[] PatternCaseLabelFollow = {TokenNameCOLON, TokenNameARROW, TokenNameCOMMA};
+	static int[] PatternCaseLabelFollow = {TokenNameCOLON, TokenNameARROW, TokenNameCOMMA, TokenNameBeginCaseExpr};
 
 	static {
 
@@ -5988,7 +6002,7 @@
 	return vs;
 }
 protected final boolean mayBeAtCasePattern(int token) {
-	return (!isInModuleDeclaration() && this.complianceLevel == ClassFileConstants.JDK17 && this.previewEnabled)
+	return (!isInModuleDeclaration() && JavaFeature.PATTERN_MATCHING_IN_SWITCH.isSupported(this.complianceLevel, this.previewEnabled))
 			&& (token == TokenNamecase || this.multiCaseLabelComma);
 }
 protected final boolean mayBeAtBreakPreview() {
@@ -6382,12 +6396,7 @@
 		// add fake token of TokenNameCOLON, call vanguard on this modified source
 		// TODO: Inefficient method due to redoing of the same source, investigate alternate
 		// Can we do a dup of parsing/check the transition of the state?
-		char[] nSource = CharOperation.append(Arrays.copyOfRange(scanner.source, scanner.caseStartPosition, scanner.startPosition), ':');
-		VanguardParser vp = getNewVanguardParser(nSource);
-		if (vp.parse(Goal.SwitchLabelCaseLhsGoal) == VanguardParser.SUCCESS) {
-			scanner.nextToken = TokenNameARROW;
-			return TokenNameBeginCaseExpr;
-		}
+		return disambiguateArrowWithCaseExpr(scanner, token);
 	} else	if (token == TokenNameLPAREN  && maybeAtLambdaOrCast()) {
 		if (parser.parse(Goal.LambdaParameterListGoal) == VanguardParser.SUCCESS) {
 			scanner.nextToken = TokenNameLPAREN;
@@ -6423,6 +6432,17 @@
 	}
 	return token;
 }
+
+protected int disambiguateArrowWithCaseExpr(Scanner scanner, int retToken) {
+	char[] nSource = CharOperation.append(Arrays.copyOfRange(scanner.source, scanner.caseStartPosition, scanner.startPosition), ':');
+	VanguardParser vp = getNewVanguardParser(nSource);
+	if (vp.parse(Goal.SwitchLabelCaseLhsGoal) == VanguardParser.SUCCESS) {
+		scanner.nextToken = TokenNameARROW;
+		retToken = TokenNameBeginCaseExpr;
+//		scanner.caseStartPosition = scanner.caseStartStack.isEmpty() ? -1 : scanner.caseStartStack.pop();
+	}
+	return retToken;
+}
 /*
  * Assumption: mayBeAtCasePattern(token) is true before calling this method.
  */
@@ -6431,6 +6451,7 @@
 	int delta = token == TokenNamecase ? 4 : 0; // 4 for case.
 	final VanguardParser parser = getNewVanguardParser();
 	parser.scanner.resetTo(parser.scanner.currentPosition + delta, parser.scanner.eofPosition);
+	parser.scanner.caseStartPosition = this.caseStartPosition;
 	if (parser.parse(Goal.PatternGoal) == VanguardParser.SUCCESS) {
 		if (token == TokenNamecase) {
 			scanner.nextToken = TokenNameBeginCaseElement;
@@ -6442,11 +6463,11 @@
 	return token;
 }
 
-private boolean mayBeAtCaseLabelExpr() {
+protected boolean mayBeAtCaseLabelExpr() {
 	if (isInModuleDeclaration() || this.caseStartPosition <= 0)
 		return false;
 	if (this.lookBack[1] == TokenNamedefault) {
-		return this.complianceLevel == ClassFileConstants.JDK17 && this.previewEnabled ?
+		return JavaFeature.PATTERN_MATCHING_IN_SWITCH.isSupported(this.complianceLevel, this.previewEnabled) ?
 				(this.lookBack[0] == TerminalTokens.TokenNamecase || this.lookBack[0] == TerminalTokens.TokenNameCOMMA)
 				: false;
 	}
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 ce75176..ce24bab 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
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2019 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -37,7 +37,8 @@
 	    TokenNameWHITESPACE = 1000,
 		TokenNameCOMMENT_LINE = 1001,
 		TokenNameCOMMENT_BLOCK = 1002,
-		TokenNameCOMMENT_JAVADOC = 1003;
+		TokenNameCOMMENT_JAVADOC = 1003,
+		TokenNameSingleQuoteStringLiteral = 1004;
 
 	// BEGIN_AUTOGENERATED_REGION
 	int TokenNameIdentifier = 14,
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser1.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser1.rsc
index d0e7d00..bb25ad8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser1.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser1.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser15.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser15.rsc
index 76f41ca..a1c68d9 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser15.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser15.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser16.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser16.rsc
index a96d6d5..5e63672 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser16.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser16.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser17.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser17.rsc
index 5321950..c6f5707 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser17.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser17.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser18.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser18.rsc
index babca65..26fd54c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser18.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser18.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser2.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser2.rsc
index 38a7bb7..f4f619b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser2.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser2.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser21.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser21.rsc
index f80fd96..38162e4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser21.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser21.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser3.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser3.rsc
index 9e58de8..c182ba5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser3.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser3.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser4.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser4.rsc
index 28f2a9f..0e7346d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser4.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser4.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser5.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser5.rsc
index 706d010..57e7fd2 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser5.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser5.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser9.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser9.rsc
index c5ff57a..4af68f8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser9.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser9.rsc
Binary files differ
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 7f50c17..7c5e1b4 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
@@ -618,6 +618,12 @@
 		case IProblem.JavadocDuplicateReturnTag:
 		case IProblem.JavadocInvalidThrowsClass:
 		case IProblem.JavadocInvalidSeeReference:
+		case IProblem.JavadocInvalidSnippet:
+		case IProblem.JavadocInvalidSnippetMissingColon:
+		case IProblem.JavadocInvalidSnippetContentNewLine:
+		case IProblem.JavadocInvalidSnippetRegexSubstringTogether:
+		case IProblem.JavadocInvalidSnippetRegionNotClosed:
+		case IProblem.JavadocInvalidSnippetDuplicateRegions:
 		case IProblem.JavadocInvalidParamTagName:
 		case IProblem.JavadocInvalidParamTagTypeParameter:
 		case IProblem.JavadocMalformedSeeReference:
@@ -6447,6 +6453,24 @@
 public void javadocInvalidReference(int sourceStart, int sourceEnd) {
 	this.handle(IProblem.JavadocInvalidSeeReference, NoArgument, NoArgument, sourceStart, sourceEnd);
 }
+public void javadocInvalidSnippet(int sourceStart, int sourceEnd) {
+	this.handle(IProblem.JavadocInvalidSnippet, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
+public void javadocInvalidSnippetMissingColon(int sourceStart, int sourceEnd) {
+	this.handle(IProblem.JavadocInvalidSnippetMissingColon, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
+public void javadocInvalidSnippetContentNewLine(int sourceStart, int sourceEnd) {
+	this.handle(IProblem.JavadocInvalidSnippetContentNewLine, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
+public void javadocInvalidSnippetRegionNotClosed(int sourceStart, int sourceEnd) {
+	this.handle(IProblem.JavadocInvalidSnippetRegionNotClosed, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
+public void javadocInvalidSnippetRegexSubstringTogether(int sourceStart, int sourceEnd) {
+	this.handle(IProblem.JavadocInvalidSnippetRegexSubstringTogether, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
+public void javadocInvalidSnippetDuplicateRegions(int sourceStart, int sourceEnd) {
+	this.handle(IProblem.JavadocInvalidSnippetDuplicateRegions, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
 /**
  * Report an invalid reference that does not conform to the href syntax.
  * Valid syntax example: @see IProblem.JavadocInvalidSeeHref
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 01261bc..8a4c8b3 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
@@ -1096,6 +1096,13 @@
 1809 = Invalid provides class
 1810 = Invalid module qualification
 1811 = {0} cannot be resolved to a module
+1812 = Space required after snippet tag
+1813 = Snippet is invalid due to missing colon
+1814 = Snippet content should be on a new line
+1815 = Region in the snippet is not closed
+1816 = Attribute regex and substring used simulataneously
+1817 = Duplicate region
+
 
 # Java 16
 1820 =  {0} is a value-based type which is a discouraged argument for the synchronized statement
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java
index 48b07d3..da7a885 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2021 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -375,7 +375,7 @@
 	 * programs written in all versions of the Java language
 	 * up to and including Java SE 16(aka JDK 16).
 	 * </p>
-	 * * @deprecated Clients should use the {@link #getJLSLatest()} AST API instead.
+	 * @deprecated Clients should use the {@link #getJLSLatest()} AST API instead.
 	 * @since 3.26
 	 */
 	public static final int JLS16 = 16;
@@ -390,10 +390,25 @@
 	 * programs written in all versions of the Java language
 	 * up to and including Java SE 17(aka JDK 17).
 	 * </p>
-	 *
+	 * @deprecated Clients should use the {@link #getJLSLatest()} AST API instead.
 	 * @since 3.28
 	 */
 	public static final int JLS17 = 17;
+	/**
+	 * Constant for indicating the AST API that handles JLS17.
+	 * <p>
+	 * This API is capable of handling all constructs in the
+	 * Java language as described in the Java Language
+	 * Specification, Java SE 18 Edition (JLS18).
+	 * JLS18 is a superset of all earlier versions of the
+	 * Java language, and the JLS18 API can be used to manipulate
+	 * programs written in all versions of the Java language
+	 * up to and including Java SE 18(aka JDK 18).
+	 * </p>
+	 *
+	 * @since 3.30
+	 */
+	public static final int JLS18 = 18;
 
 	/**
 	 * Internal synonym for {@link #JLS15}. Use to alleviate
@@ -410,19 +425,23 @@
 	 * deprecation warnings once JLS17 is deprecated
 	 */
 	static final int JLS17_INTERNAL = JLS17;
-
+	/**
+	 * Internal synonym for {@link #JLS18}. Use to alleviate
+	 * deprecation warnings once JLS18 is deprecated
+	 */
+	static final int JLS18_INTERNAL = JLS18;
 	/**
 	 * Internal property for latest supported JLS level
 	 * This provides the latest JLS level.
 	 */
-	private static final int JLS_INTERNAL_Latest = JLS17;
+	private static final int JLS_INTERNAL_Latest = JLS18;
 
 	/**
 	 * @since 3.26
 	 * This provides the latest JLS level.
 	 * @deprecated use {@link #getJLSLatest()}
 	 */
-	public static final int JLS_Latest = JLS17;
+	public static final int JLS_Latest = JLS18;
 
 	/*
 	 * Must not collide with a value for ICompilationUnit constants
@@ -1157,6 +1176,7 @@
         t.put(JavaCore.VERSION_15, ClassFileConstants.JDK15);
         t.put(JavaCore.VERSION_16, ClassFileConstants.JDK16);
         t.put(JavaCore.VERSION_17, ClassFileConstants.JDK17);
+        t.put(JavaCore.VERSION_18, ClassFileConstants.JDK18);
         return Collections.unmodifiableMap(t);
 	}
 	private static Map<String, Integer> getApiLevelMapTable() {
@@ -1178,6 +1198,7 @@
         t.put(JavaCore.VERSION_15, JLS15_INTERNAL);
         t.put(JavaCore.VERSION_16, JLS16_INTERNAL);
         t.put(JavaCore.VERSION_17, JLS17_INTERNAL);
+        t.put(JavaCore.VERSION_18, JLS18_INTERNAL);
         return Collections.unmodifiableMap(t);
 	}
 	/**
@@ -2236,6 +2257,20 @@
 //jsv}
 
 	/**
+	 * Creates and returns a new doc comment region node.
+	 * Initially the new node has an empty list of tag elements
+	 * (and, for backwards compatability, an unspecified, but legal,
+	 * doc comment string)
+	 *
+	 * @return a new unparented doc comment node
+	 * @since 3.30
+	 */
+	public JavaDocRegion newJavaDocRegion() {
+		JavaDocRegion result = new JavaDocRegion(this);
+		return result;
+	}
+
+	/**
 	 * Creates a new unparented labeled statement node owned by this AST.
 	 * By default, the label and statement are both unspecified, but legal.
 	 *
@@ -3126,7 +3161,7 @@
 
 	/**
 	 * Creates and returns a new tag element node.
-	 * Initially the new node has no tag name and an empty list of fragments.
+	 * Initially the new node has no tag name and an empty list of fragments and properties.
 	 * <p>
 	 * Note that this node type is used only inside doc comments
 	 * ({@link Javadoc}).
@@ -3141,6 +3176,22 @@
 	}
 
 	/**
+	 * Creates and returns a new tag property node.
+	 * Initially the new node has no property name and value.
+	 * <p>
+	 * Note that this node type is used only inside doc comments
+	 * ({@link Javadoc}).
+	 * </p>
+	 *
+	 * @return a new unparented tag element node
+	 * @since 3.30
+	 */
+	public TagProperty newTagProperty() {
+		TagProperty result = new TagProperty(this);
+		return result;
+	}
+
+	/**
 	 * Creates an unparented yield statement node owned by this AST. The yield statement has no
 	 * label/identifier/expression and is not implicit.
 	 *
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 bbad1ce..5799506 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
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2021 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -5404,6 +5404,7 @@
 	}
 
 	protected void recordNodes(org.eclipse.jdt.internal.compiler.ast.Javadoc javadoc, TagElement tagElement) {
+		// To do: for Tag property
 		Iterator fragments = tagElement.fragments().listIterator();
 		while (fragments.hasNext()) {
 			ASTNode node = (ASTNode) fragments.next();
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java
index 666b966..820d3aa 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2021 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -7,7 +7,6 @@
  * https://www.eclipse.org/legal/epl-2.0/
  *
  * SPDX-License-Identifier: EPL-2.0
- *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Fraunhofer FIRST - extended API and implementation
@@ -1321,6 +1320,32 @@
 	}
 
 	/**
+	 * Returns whether the given node and the other object match.
+	 * <p>
+	 * The default implementation provided by this class tests whether the
+	 * other object is a node of the same type with structurally isomorphic
+	 * child subtrees. Subclasses may override this method as needed.
+	 * </p>
+	 *
+	 * @param node the node
+	 * @param other the other object, or <code>null</code>
+	 * @return <code>true</code> if the subtree matches, or
+	 *   <code>false</code> if they do not match or the other object has a
+	 *   different node type or is <code>null</code>
+	 * @see #ASTMatcher()
+	 * @see #ASTMatcher(boolean)
+	 * @since 3.30
+	 */
+	public boolean match(JavaDocRegion node, Object other) {
+		if (!(other instanceof JavaDocRegion)) {
+			return false;
+		}
+		JavaDocRegion o = (JavaDocRegion) other;
+		return safeEquals(node.getTagName(), o.getTagName()) && safeSubtreeListMatch(node.tags(), o.tags()) && safeSubtreeListMatch(node.fragments(), o.fragments())
+				&& safeEquals(node.isDummyRegion(), o.isDummyRegion() && safeEquals(node.isValidSnippet(), o.isValidSnippet()));
+	}
+
+	/**
 	 * Return whether the deprecated comment strings of the given java doc are equals.
 	 * <p>
 	 * Note the only purpose of this method is to hide deprecated warnings.
@@ -2533,7 +2558,34 @@
 		TagElement o = (TagElement) other;
 		return (
 				safeEquals(node.getTagName(), o.getTagName())
-				&& safeSubtreeListMatch(node.fragments(), o.fragments()));
+				&& safeSubtreeListMatch(node.fragments(), o.fragments())
+				&& (DOMASTUtil.isJavaDocCodeSnippetSupported(node.getAST().apiLevel)? safeSubtreeListMatch(node.tagProperties(), o.tagProperties()) : true));
+	}
+
+	/**
+	 * Returns whether the given node and the other object match.
+	 * <p>
+	 * The default implementation provided by this class tests whether the
+	 * other object is a node of the same type with structurally isomorphic
+	 * child subtrees. Subclasses may override this method as needed.
+	 * </p>
+	 *
+	 * @param node the node
+	 * @param other the other object, or <code>null</code>
+	 * @return <code>true</code> if the subtree matches, or
+	 *   <code>false</code> if they do not match or the other object has a
+	 *   different node type or is <code>null</code>
+	 * @since 3.30
+	 */
+	public boolean match(TagProperty node, Object other) {
+		if (!(other instanceof TagProperty)) {
+			return false;
+		}
+		TagProperty o = (TagProperty) other;
+		return (
+				safeEquals(node.getName(), o.getName())
+				&& safeEquals(node.getStringValue(), o.getStringValue()))
+				&& safeSubtreeMatch(node.getNodeValue(), o.getNodeValue());
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java
index d32faed..71f809b 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2021 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -1036,8 +1036,24 @@
 	 */
 	public static final int CASE_DEFAULT_EXPRESSION = 109;
 
+	/**
+	 * Node type constant indicating a node of type
+	 * <code>TagProperty</code>.
+	 * @see TagProperty
+	 * @since 3.30
+	 */
+	public static final int TAG_PROPERTY = 110;
+
+	/**
+	 * Node type constant indicating a node of type
+	 * <code>JavaDocRegion</code>.
+	 * @see JavaDocRegion
+	 * @since 3.30
+	 */
+	public static final int JAVADOC_REGION = 111;
+
 //{ObjectTeams: required OT specific node type constants added
-	private static final int LAST_JDT = 109;
+	private static final int LAST_JDT = 111;
 
 	/**
 	 * Node type constant indicating a node of type
@@ -1231,6 +1247,8 @@
 				return IntersectionType.class;
 			case JAVADOC :
 				return Javadoc.class;
+			case JAVADOC_REGION :
+				return JavaDocRegion.class;
 			case LABELED_STATEMENT :
 				return LabeledStatement.class;
 			case LAMBDA_EXPRESSION :
@@ -1325,6 +1343,8 @@
 				return SynchronizedStatement.class;
 			case TAG_ELEMENT :
 				return TagElement.class;
+			case TAG_PROPERTY :
+				return TagProperty.class;
 			case TEXT_BLOCK :
 				return TextBlock.class;
 			case TEXT_ELEMENT :
@@ -2404,6 +2424,22 @@
 		}
 	}
 
+	/**
+     * Checks that this AST operation is not used when
+     * building JLS2, JLS3, JLS4, JLS8, JLS9, JLS10, JLS11, JLS12, JLS13, JSL14, JSL15, JLS16 or JLS17 level ASTs.
+     * <p>
+     * Use this method to prevent access to new properties that have been added in JLS18
+     * </p>
+     *
+	 * @exception UnsupportedOperationException if this operation is used below JLS18
+	 * @since 3.30
+	 */
+	final void unsupportedBelow18() {
+		if (this.ast.apiLevel < AST.JLS18_INTERNAL) {
+			throw new UnsupportedOperationException("Operation only supported in ASTs with level JLS17 and above"); //$NON-NLS-1$
+		}
+	}
+
 
 	/**
      * Checks that this AST operation is not used when
@@ -2551,6 +2587,21 @@
 			throw new UnsupportedOperationException("Operation only supported in JLS17 AST"); //$NON-NLS-1$
 		}
 	}
+	/**
+ 	 * Checks that this AST operation is only used when
+     * building JLS18 level ASTs.
+     * <p>
+     * Use this method to prevent access to new properties available only in JLS18.
+     * </p>
+     *
+	 * @exception UnsupportedOperationException if this operation is not used in JLS18
+	 * @since 3.30
+	 */
+	final void supportedOnlyIn18() {
+		if (this.ast.apiLevel != AST.JLS18_INTERNAL) {
+			throw new UnsupportedOperationException("Operation only supported in JLS17 AST"); //$NON-NLS-1$
+		}
+	}
 
 	/**
 	 * Sets or clears this node's parent node and location.
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTParser.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTParser.java
index e60ae78..82a6ded 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTParser.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTParser.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2021 IBM Corporation and others.
+ * Copyright (c) 2004, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -1292,7 +1292,8 @@
 								sourceUnit,
 								searcher,
 								this.compilerOptions,
-								flags);
+								flags,
+								this.project);
 						needToResolveBindings = false;
 					}
 					CompilationUnit result = CompilationUnitResolver.convert(
@@ -1305,7 +1306,8 @@
 						needToResolveBindings ? new DefaultBindingResolver.BindingTables() : null,
 						flags,
 						monitor,
-						this.project != null);
+						this.project != null,
+						this.project);
 					result.setTypeRoot(this.typeRoot);
 					return result;
 				} finally {
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java
index c53eb0c..4d48e6e 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2021 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -7,6 +7,8 @@
  * https://www.eclipse.org/legal/epl-2.0/
  *
  * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Fraunhofer FIRST - extended API and implementation
  *     Technical University Berlin - extended API and implementation
@@ -899,6 +901,28 @@
 	}
 
 	/**
+	 * Visits the given AST node.
+	 * <p>
+	 * Unlike other node types, the boolean returned by the default
+	 * implementation is controlled by a constructor-supplied
+	 * parameter  {@link #ASTVisitor(boolean) ASTVisitor(boolean)}
+	 * which is <code>false</code> by default.
+	 * Subclasses may reimplement.
+	 * </p>
+	 *
+	 * @param node the node to visit
+	 * @return <code>true</code> if the children of this node should be
+	 * visited, and <code>false</code> if the children of this node should
+	 * be skipped
+	 * @see #ASTVisitor()
+	 * @see #ASTVisitor(boolean)
+	 * @since 3.30
+	 */
+	public boolean visit(JavaDocRegion node) {
+		return this.visitDocTags;
+	}
+
+	/**
 	 * Visits the given type-specific AST node.
 	 * <p>
 	 * The default implementation does nothing and return true.
@@ -1692,6 +1716,23 @@
 		return true;
 	}
 
+	/**
+	 * Visits the given type-specific AST node.
+	 * <p>
+	 * The default implementation does nothing and return true.
+	 * Subclasses may reimplement.
+	 * </p>
+	 *
+	 * @param node the node to visit
+	 * @return <code>true</code> if the children of this node should be
+	 * visited, and <code>false</code> if the children of this node should
+	 * be skipped
+	 * @since 3.30
+	 */
+	public boolean visit(TagProperty node) {
+		return true;
+	}
+
 
 	/**
 	 * Visits the given type-specific AST node.
@@ -2525,6 +2566,19 @@
 	 * </p>
 	 *
 	 * @param node the node to visit
+	 * @since 3.30
+	 */
+	public void endVisit(JavaDocRegion node) {
+		// default implementation: do nothing
+	}
+
+	/**
+	 * End of visit the given type-specific AST node.
+	 * <p>
+	 * The default implementation does nothing. Subclasses may reimplement.
+	 * </p>
+	 *
+	 * @param node the node to visit
 	 */
 	public void endVisit(ConstructorInvocation node) {
 		// default implementation: do nothing
@@ -3110,6 +3164,19 @@
 	 * </p>
 	 *
 	 * @param node the node to visit
+	 * @since 3.30
+	 */
+	public void endVisit(TagProperty node) {
+		// default implementation: do nothing
+	}
+
+	/**
+	 * End of visit the given type-specific AST node.
+	 * <p>
+	 * The default implementation does nothing. Subclasses may reimplement.
+	 * </p>
+	 *
+	 * @param node the node to visit
 	 */
 	public void endVisit(ParenthesizedExpression node) {
 		// default implementation: do nothing
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AbstractTagElement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AbstractTagElement.java
new file mode 100644
index 0000000..332acc4
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AbstractTagElement.java
@@ -0,0 +1,241 @@
+/*******************************************************************************
+ * Copyright (c) 2022 IBM Corporation 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
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.List;
+
+/**
+ * AST node for a tag within a doc comment.
+ * Tag elements nested within another tag element are called
+ * inline doc tags.
+ * <pre>
+ * TagElement:
+ *     [ <b>@</b> Identifier ] { DocElement }
+ *     {tagProperty = tagValue}
+ * DocElement:
+ *     TextElement
+ *     Name
+ *     MethodRef
+ *     MemberRef
+ *     <b>{</b> TagElement <b>}</b>
+ * </pre>
+ *
+ * @see Javadoc
+ * @since 3.30
+ */
+
+@SuppressWarnings("rawtypes")
+public abstract class AbstractTagElement extends ASTNode implements IDocElement {
+
+	/**
+	 * The "tagName" structural property of this node type (type: {@link String}).
+	 *
+	 * @since 3.30
+	 */
+	public static final SimplePropertyDescriptor internalTagNamePropertyFactory(Class nodeClass) {
+		return new SimplePropertyDescriptor(nodeClass, "tagName", String.class, OPTIONAL); //$NON-NLS-1$
+ 	}
+
+	/**
+	 * The "fragments" structural property of this node type (element type: {@link IDocElement}).
+	 * @since 3.30
+	 */
+
+	static final ChildListPropertyDescriptor internalFragmentsPropertyFactory(Class nodeClass) {
+		return new ChildListPropertyDescriptor(nodeClass, "fragments", IDocElement.class, CYCLE_RISK); //$NON-NLS-1$
+	}
+
+
+	/**
+	 * The tag name, or null if none; defaults to null.
+	 */
+	String optionalTagName = null;
+
+	/**
+	 * The list of doc elements (element type: {@link IDocElement}).
+	 * Defaults to an empty list.
+	 */
+	ASTNode.NodeList fragments = new ASTNode.NodeList(internalFragmentsPropertyFactory());
+
+
+	/**
+	 * Creates a new AST node for a tag element owned by the given AST.
+	 * The new node has no name and an empty list of fragments.
+	 * <p>
+	 * N.B. This constructor is package-private; all subclasses must be
+	 * declared in the same package; clients are unable to declare
+	 * additional subclasses.
+	 * </p>
+	 *
+	 * @param ast the AST that is to own this node
+	 */
+	AbstractTagElement(AST ast) {
+		super(ast);
+		this.fragments = new ASTNode.NodeList(internalFragmentsPropertyFactory());
+	}
+
+	/**
+	 * Returns structural property descriptor for the "fragments" property
+	 * of this node (element type: {@link IDocElement}).
+	 *
+	 * @return the property descriptor
+	 */
+	abstract ChildListPropertyDescriptor internalFragmentsPropertyFactory();
+
+	/**
+	 * Returns structural property descriptor for the "tagName" property
+	 * of this node (element type: {@link String}).
+	 *
+	 * @return the property descriptor
+	 */
+	abstract SimplePropertyDescriptor internalTagNamePropertyFactory();
+
+
+	/**
+	 * Returns structural property descriptor for the "name" property
+	 * of this node (child type: {@link SimpleName}).
+	 *
+	 * @return the property descriptor
+	 * @since 3.1
+	 */
+	public final SimplePropertyDescriptor getTagNameProperty() {
+		return internalTagNamePropertyFactory();
+	}
+
+	@Override
+	final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+		if (property == internalTagNamePropertyFactory()) {
+			if (get) {
+				return getTagName();
+			} else {
+				setTagName((String) value);
+				return null;
+			}
+		}
+		// allow default implementation to flag the error
+		return super.internalGetSetObjectProperty(property, get, value);
+	}
+	/**
+	 * Returns this node's tag name, or <code>null</code> if none.
+	 * For top level doc tags such as parameter tags, the tag name
+     * includes the "@" character ("@param").
+	 * For inline doc tags such as link tags, the tag name
+     * includes the "@" character ("@link").
+     * The tag name may also be <code>null</code>; this is used to
+     * represent the material at the start of a doc comment preceding
+     * the first explicit tag.
+     *
+	 * @return the tag name, or <code>null</code> if none
+	 */
+	public String getTagName() {
+		return this.optionalTagName;
+	}
+
+	/**
+	 * Sets the tag name of this node to the given value.
+	 * For top level doc tags such as parameter tags, the tag name
+	 * includes the "@" character ("@param").
+	 * For inline doc tags such as link tags, the tag name
+	 * includes the "@" character ("@link").
+	 * The tag name may also be <code>null</code>; this is used to
+	 * represent the material at the start of a doc comment preceding
+	 * the first explicit tag.
+	 *
+	 * @param tagName the tag name, or <code>null</code> if none
+	 */
+	public void setTagName(String tagName) {
+		preValueChange(internalTagNamePropertyFactory());
+		this.optionalTagName = tagName;
+		postValueChange(internalTagNamePropertyFactory());
+	}
+
+	/**
+	 * Returns the live list of fragments in this tag element.
+	 * <p>
+	 * The fragments cover everything following the tag name
+	 * (or everything if there is no tag name), and generally omit
+	 * embedded line breaks (and leading whitespace on new lines,
+	 * including any leading "*"). {@link org.eclipse.jdt.core.dom.AbstractTagElement}
+	 * nodes are used to represent tag elements (e.g., "@link")
+	 * nested within this tag element.
+	 * </p>
+	 * <p>
+	 * Here are some typical examples:
+	 * <ul>
+	 * <li>"@see Foo#bar()" - TagElement with tag name "@see";
+	 * fragments() contains a single MethodRef node</li>
+	 * <li>"@param args the program arguments" -
+	 * TagElement with tag name "@param";
+	 * 2 fragments: SimpleName ("args"), TextElement
+	 * (" the program arguments")</li>
+	 * <li>"@return See {&#64;link #foo foo} instead." -
+	 * TagElement with tag name "@return";
+	 * 3 fragments: TextElement ("See "),
+	 * TagElement (for "&#64;link #foo foo"),
+	 * TextElement (" instead.")</li>
+	 * </ul>
+	 * The use of Name, MethodRef, and MemberRef nodes within
+	 * tag elements allows these fragments to be queried for
+	 * binding information.
+	 * <p>
+	 * Adding and removing nodes from this list affects this node
+	 * dynamically. The nodes in this list may be of various
+	 * types, including {@link TextElement},
+	 * {@link org.eclipse.jdt.core.dom.AbstractTagElement}, {@link Name},
+	 * {@link MemberRef}, and {@link MethodRef}.
+	 * Clients should assume that the list of types may grow in
+	 * the future, and write their code to deal with unexpected
+	 * nodes types. However, attempts to add a non-prescribed type
+	 * of node will trigger an exception.
+	 *
+	 * @return the live list of doc elements in this tag element
+	 * (element type: {@link IDocElement})
+	 */
+	public List fragments() {
+		return this.fragments;
+	}
+
+	/**
+	 * Returns whether this tag element is nested within another
+	 * tag element. Nested tag elements appears enclosed in
+	 * "{" and "}"; certain doc tags, including "@link" and
+	 * "@linkplain" are only meaningful as nested tags.
+	 * Top-level (i.e., non-nested) doc tags begin on a new line;
+	 * certain doc tags, including "@param" and
+	 * "@see" are only meaningful as top-level tags.
+	 * <p>
+	 * This convenience methods checks to see whether the parent
+	 * of this node is of type {@link org.eclipse.jdt.core.dom.AbstractTagElement}.
+	 * </p>
+	 *
+	 * @return <code>true</code> if this node is a nested tag element,
+	 * and false if this node is either parented by a doc comment node
+	 * ({@link Javadoc}), or is unparented
+	 */
+	public boolean isNested() {
+		return (getParent() instanceof AbstractTagElement);
+	}
+
+	@Override
+	int memSize() {
+		int size = BASE_NODE_SIZE + 2 * 3 + stringSize(this.optionalTagName);
+		return size;
+	}
+
+	@Override
+	int treeSize() {
+		return memSize() + this.fragments.listSize();
+	}
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java
index e6b3fd1..fbae13a 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2019 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -26,9 +26,12 @@
 import java.util.List;
 import java.util.Map;
 
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.OperationCanceledException;
 import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.jdt.core.IClasspathEntry;
 import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IJavaProject;
@@ -67,6 +70,7 @@
 import org.eclipse.jdt.internal.core.BinaryModule;
 import org.eclipse.jdt.internal.core.CancelableNameEnvironment;
 import org.eclipse.jdt.internal.core.CancelableProblemFactory;
+import org.eclipse.jdt.internal.core.ClasspathEntry;
 import org.eclipse.jdt.internal.core.INameEnvironmentWithProgress;
 import org.eclipse.jdt.internal.core.JavaProject;
 import org.eclipse.jdt.internal.core.LocalVariable;
@@ -303,6 +307,21 @@
 			int flags,
 			IProgressMonitor monitor,
 			boolean fromJavaProject) {
+		return convert(compilationUnitDeclaration, source,apiLevel, options, needToResolveBindings, owner, bindingTables,
+				flags, monitor, fromJavaProject, null);
+	}
+	public static CompilationUnit convert(
+			CompilationUnitDeclaration compilationUnitDeclaration,
+			char[] source,
+			int apiLevel,
+			Map options,
+			boolean needToResolveBindings,
+			WorkingCopyOwner owner,
+			DefaultBindingResolver.BindingTables bindingTables,
+			int flags,
+			IProgressMonitor monitor,
+			boolean fromJavaProject,
+			IJavaProject project) {
 		BindingResolver resolver = null;
 		AST ast = AST.newAST(apiLevel, JavaCore.ENABLED.equals(options.get(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES)));
 		String sourceModeSetting = (String) options.get(JavaCore.COMPILER_SOURCE);
@@ -331,6 +350,8 @@
 		}
 		ast.setBindingResolver(resolver);
 		converter.setAST(ast);
+		converter.docParser.setProjectPath(CompilationUnitResolver.getProjectPath(project));
+		converter.docParser.setProjectSrcClasspath(CompilationUnitResolver.getSourceClassPaths(project));
 		compilationUnit = converter.convert(compilationUnitDeclaration, source);
 		compilationUnit.setLineEndTable(compilationUnitDeclaration.compilationResult.getLineSeparatorPositions());
 		ast.setDefaultNodeFlag(0);
@@ -338,6 +359,48 @@
 		return compilationUnit;
 	}
 
+	/**
+	 * @return absolute path in local file system, may return {@code null}
+	 */
+	private static String getProjectPath(IJavaProject project) {
+		if(project == null) {
+			return null;
+		}
+		IProject rp = project.getProject();
+		if (rp == null) {
+			return null;
+		}
+		IPath location = rp.getLocation();
+		if(location == null) {
+			return null;
+		}
+		return location.toOSString();
+	}
+	private static ArrayList<String> getSourceClassPaths(IJavaProject project) {
+		ArrayList<String> srcClassPath = new ArrayList<>();
+		if(project == null)
+			return srcClassPath;
+		if(project.getProject() == null)
+			return srcClassPath;
+		IClasspathEntry[] resolvedClasspath = null;
+		try {
+			resolvedClasspath = project.getResolvedClasspath(true);
+		} catch (JavaModelException e) {
+			//do nothing
+		}
+
+		for (IClasspathEntry entry : resolvedClasspath) {
+		    if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+		    	if(entry instanceof ClasspathEntry) {
+		    		IPath path = ((ClasspathEntry)entry).getPath();
+		    		srcClassPath.add(path.removeFirstSegments(1).toString());
+		    	}
+		    }
+		}
+		return srcClassPath;
+	}
+
+
 	protected static CompilerOptions getCompilerOptions(Map options, boolean statementsRecovery) {
 		CompilerOptions compilerOptions = new CompilerOptions(options);
 		compilerOptions.performMethodsFullRecovery = statementsRecovery;
@@ -526,11 +589,19 @@
 			astRequestor.acceptAST(sourceUnits[i], node);
 		}
 	}
+
 	public static CompilationUnitDeclaration parse(
 			org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit,
 			NodeSearcher nodeSearcher,
 			Map settings,
 			int flags) {
+		return parse(sourceUnit, nodeSearcher, settings, flags, null);
+	}
+	public static CompilationUnitDeclaration parse(
+			org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit,
+			NodeSearcher nodeSearcher,
+			Map settings,
+			int flags, IJavaProject project) {
 		if (sourceUnit == null) {
 			throw new IllegalStateException();
 		}
@@ -545,6 +616,11 @@
 					compilerOptions,
 					new DefaultProblemFactory()),
 			false);
+		if (project != null) {
+			parser.javadocParser.setProjectPath(getProjectPath(project));
+			parser.javadocParser.setProjectSrcClasspath(getSourceClassPaths(project));
+
+		}
 		CompilationResult compilationResult = new CompilationResult(sourceUnit, 0, 0, compilerOptions.maxProblemsPerUnit);
 		CompilationUnitDeclaration compilationUnitDeclaration = parser.dietParse(sourceUnit, compilationResult);
 
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultASTVisitor.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultASTVisitor.java
index fc66de7..10a0dbb 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultASTVisitor.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultASTVisitor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2019 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -7,7 +7,8 @@
  * https://www.eclipse.org/legal/epl-2.0/
  *
  * SPDX-License-Identifier: EPL-2.0
- *Contributors:
+ *
+ * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
 package org.eclipse.jdt.core.dom;
@@ -353,6 +354,10 @@
 		endVisitNode(node);
 	}
 	@Override
+	public void endVisit(TagProperty node) {
+		endVisitNode(node);
+	}
+	@Override
 	public void endVisit(TextBlock node) {
 		endVisitNode(node);
 	}
@@ -764,6 +769,11 @@
 	}
 
 	@Override
+	public boolean visit(TagProperty node) {
+		return visitNode(node);
+	}
+
+	@Override
 	public boolean visit(TextBlock node) {
 		return visitNode(node);
 	}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DocCommentParser.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DocCommentParser.java
index 832c912..cfe0d5f 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DocCommentParser.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DocCommentParser.java
@@ -13,8 +13,10 @@
  *******************************************************************************/
 package org.eclipse.jdt.core.dom;
 
+import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.compiler.InvalidInputException;
@@ -223,6 +225,44 @@
 
 	@Override
 	protected void createTag() {
+		int position = this.scanner.currentPosition;
+		this.scanner.resetTo(this.tagSourceStart, this.tagSourceEnd);
+		StringBuilder tagName = new StringBuilder();
+		int start = this.tagSourceStart;
+		this.scanner.getNextChar();
+		while (this.scanner.currentPosition <= (this.tagSourceEnd+1)) {
+			tagName.append(this.scanner.currentCharacter);
+			this.scanner.getNextChar();
+		}
+		if (TagElement.TAG_SNIPPET.equals(tagName.toString())) {
+			this.tagSourceEnd = this.index;
+			// need to use createSnippetTag to create @snippet
+			return;
+		}
+		TagElement tagElement = this.ast.newTagElement();
+		tagElement.setTagName(tagName.toString());
+		if (this.inlineTagStarted) {
+			start = this.inlineTagStart;
+			TagElement previousTag = null;
+			if (this.astPtr == -1) {
+				previousTag = this.ast.newTagElement();
+				previousTag.setSourceRange(start, this.tagSourceEnd-start+1);
+				pushOnAstStack(previousTag, true);
+			} else {
+				previousTag = (TagElement) this.astStack[this.astPtr];
+			}
+			int previousStart = previousTag.getStartPosition();
+			previousTag.fragments().add(tagElement);
+			previousTag.setSourceRange(previousStart, this.tagSourceEnd-previousStart+1);
+		} else {
+			pushOnAstStack(tagElement, true);
+		}
+		tagElement.setSourceRange(start, this.tagSourceEnd-start+1);
+		this.scanner.resetTo(position, this.javadocEnd);
+	}
+
+	@Override
+	protected Object createSnippetTag() {
 		TagElement tagElement = this.ast.newTagElement();
 		int position = this.scanner.currentPosition;
 		this.scanner.resetTo(this.tagSourceStart, this.tagSourceEnd);
@@ -252,9 +292,244 @@
 		}
 		tagElement.setSourceRange(start, this.tagSourceEnd-start+1);
 		this.scanner.resetTo(position, this.javadocEnd);
+		return tagElement;
 	}
 
 	@Override
+	protected void setSnippetIsValid(Object tag, boolean value) {
+		if (tag instanceof TagElement) {
+			((TagElement) tag).setProperty(TagProperty.TAG_PROPERTY_SNIPPET_IS_VALID, value);
+		}
+	}
+
+	@Override
+	protected void setSnippetError(Object tag, String value) {
+		if (tag instanceof TagElement) {
+			((TagElement) tag).setProperty(TagProperty.TAG_PROPERTY_SNIPPET_ERROR, value);
+		}
+	}
+
+	@Override
+	protected void setSnippetID(Object tag, String value) {
+		if (tag instanceof TagElement) {
+			((TagElement) tag).setProperty(TagProperty.TAG_PROPERTY_SNIPPET_ID, value);
+		}
+	}
+
+	@Override
+	protected Object createSnippetRegion(String name, List<Object> tags, Object snippetTag, boolean isDummyRegion, boolean considerPrevTag) {
+		if (!isDummyRegion) {
+			return createSnippetOriginalRegion(name, tags);
+		}
+		List<TagElement> tagsToBeProcessed = new ArrayList<>();
+		Object toBeReturned = null;
+		if (tags != null && tags.size() > 0) {
+			int start = -1;
+			int end = -1;
+			for (Object tag : tags) {
+				if (tag instanceof TagElement) {
+					TagElement tagElem = (TagElement) tag;
+					tagsToBeProcessed.add(tagElem);
+					int tagStart = tagElem.getStartPosition();
+					int tagEnd = tagStart + tagElem.getLength();
+					if (start == -1 || start > tagStart) {
+						start = tagStart;
+					}
+					if (end ==-1 || end < tagEnd) {
+						end = tagEnd;
+					}
+				} else if (tag instanceof JavaDocRegion && snippetTag instanceof TagElement) {
+					TagElement snippet = (TagElement) snippetTag;
+					JavaDocRegion reg = (JavaDocRegion) tag;
+					if (!reg.isDummyRegion()) {
+						snippet.fragments().add(reg);
+					}
+					toBeReturned = reg;
+				}
+			}
+			if (tagsToBeProcessed.size() > 0) {
+				boolean process = true;
+				if (considerPrevTag && snippetTag instanceof TagElement) {
+					TagElement snippetTagElem = (TagElement) snippetTag;
+					Object prevTag = snippetTagElem.fragments().get(snippetTagElem.fragments().size() - 1);
+					if (prevTag instanceof TagElement) {
+						tagsToBeProcessed.add(0, (TagElement)prevTag);
+						snippetTagElem.fragments().remove(prevTag);
+					} else if (prevTag instanceof JavaDocRegion) {
+						JavaDocRegion region = (JavaDocRegion) prevTag;
+						region.tags().addAll(tagsToBeProcessed);
+						toBeReturned = snippetTag;
+						process = false;
+					}
+				}
+				if (process) {
+					if (tagsToBeProcessed.size() == 1) {
+						return tagsToBeProcessed.get(0);
+					}
+					else {
+						JavaDocRegion region = this.ast.newJavaDocRegion();
+						region.tags().addAll(tagsToBeProcessed);
+						region.setSourceRange(start, end);
+						toBeReturned = region;
+					}
+				}
+			} else {
+				toBeReturned = snippetTag;
+			}
+		}
+		return toBeReturned;
+	}
+
+	private Object createSnippetOriginalRegion(String name, List<Object> tags) {
+		JavaDocRegion region = this.ast.newJavaDocRegion();
+		if (tags != null && tags.size() > 0) {
+			int start = -1;
+			int end = -1;
+			for (Object tag : tags) {
+				if (tag instanceof TagElement) {
+					TagElement tagElem = (TagElement) tag;
+					region.tags().add(tagElem);
+					int tagStart = tagElem.getStartPosition();
+					int tagEnd = tagStart + tagElem.getLength();
+					if (start == -1 || start > tagStart) {
+						start = tagStart;
+					}
+					if (end ==-1 || end < tagEnd) {
+						end = tagEnd;
+					}
+				}
+			}
+			region.setSourceRange(start, end-start);
+			region.setDummyRegion(false);
+		}
+		if (name != null) {
+			region.setTagName(name);
+		}
+		return region;
+	}
+
+	@Override
+	protected Object createSnippetInnerTag(String tagName, int start, int end) {
+		if (tagName != null) {
+			TagElement tagElement = this.ast.newTagElement();
+			tagElement.setTagName(tagName.toString());
+			if (this.astPtr == -1) {
+				return null;
+			}
+			tagElement.setSourceRange(start, end-start);
+			return tagElement;
+		}
+		return null;
+	}
+
+	@Override
+	protected void closeJavaDocRegion(String name, Object snippetTag, int end) {
+		if (snippetTag instanceof TagElement) {
+			TagElement snippet = (TagElement) snippetTag;
+			List<JavaDocRegion> regions = snippet.tagRegions();
+			JavaDocRegion regionToClose = null;
+			if (name != null) {
+				for (JavaDocRegion region : regions) {
+					if (name.equals(region.getTagName())) {
+						if (!this.isRegionToBeEnded(region)
+								&& !this.hasRegionEnded(region)) {
+							regionToClose = region;
+							break;
+						}
+					}
+				}
+			} else {
+				for (int i= regions.size()-1; i >-1; i--) {
+					JavaDocRegion region = regions.get(i);
+					if (!this.isRegionToBeEnded(region)
+							&& !this.hasRegionEnded(region)) {
+						regionToClose = region;
+						break;
+					}
+				}
+			}
+			if (regionToClose != null) {
+				setRegionToBeEnded(regionToClose, true);
+				int start = regionToClose.getStartPosition();
+				int curEnd = start + regionToClose.getLength();
+				if (end > curEnd) {
+					regionToClose.setSourceRange(start, end-start);
+				}
+			}
+		}
+
+	}
+
+	@Override
+	protected void addTagProperties(Object tag, Map<String, Object> map, int tagCount) {
+		if (tag instanceof TagElement) {
+			TagElement tagElement = (TagElement) tag;
+			map.forEach((k, v) -> {
+				TagProperty tagProperty = this.ast.newTagProperty();
+				tagProperty.setName(k);
+				if (v instanceof String) {
+					tagProperty.setStringValue((String)v);
+				} else if (v instanceof ASTNode) {
+					tagProperty.setNodeValue((ASTNode)v);
+				}
+				tagElement.tagProperties().add(tagProperty);
+			});
+			tagElement.setProperty(TagProperty.TAG_PROPERTY_SNIPPET_INLINE_TAG_COUNT, tagCount);
+		}
+	}
+
+	@Override
+	protected void addSnippetInnerTag(Object obj, Object snippetTag) {
+		boolean isNotDummyRegion = false;
+		if (obj instanceof JavaDocRegion) {
+			JavaDocRegion region = (JavaDocRegion) obj;
+			if (snippetTag instanceof TagElement) {
+				TagElement snippetTagElem = (TagElement) snippetTag;
+				if (!region.isDummyRegion()) {
+					snippetTagElem.fragments().add(region);
+					isNotDummyRegion = true;
+				} else {
+					Iterator<Object> itr = region.tags().iterator();
+					while (itr.hasNext()) {
+						Object tag = itr.next();
+						if (tag instanceof JavaDocRegion) {
+							JavaDocRegion reg = (JavaDocRegion) tag;
+							if (!reg.isDummyRegion()) {
+								region.tags().remove(reg);
+								snippetTagElem.fragments().add(reg);
+							}
+						}
+					}
+				}
+			}
+		}
+		if (obj instanceof AbstractTagElement && !isNotDummyRegion) {
+			AbstractTagElement tagElement = (AbstractTagElement) obj;
+			AbstractTagElement previousTag = null;
+			if (this.astPtr == -1) {
+				return;
+			} else {
+				previousTag = (AbstractTagElement) this.astStack[this.astPtr];
+				List fragments = previousTag.fragments();
+				if (this.inlineTagStarted) {
+					int size = fragments.size();
+					if (size == 0) {
+						//do nothing
+					} else {
+						// If last fragment is a tag, then use it as previous tag
+						ASTNode lastFragment = (ASTNode) fragments.get(size-1);
+						if (lastFragment instanceof AbstractTagElement) {
+							previousTag = (AbstractTagElement) lastFragment;
+						}
+					}
+				}
+			}
+			previousTag.fragments().add(tagElement);
+		}
+	}
+
+
+	@Override
 	protected Object createTypeReference(int primitiveToken, boolean canBeModule) {
 		return createTypeReference(primitiveToken);
 	}
@@ -572,6 +847,15 @@
 							} else {
 								valid = parseReference(true);
 							}
+						} else if (length == TAG_SNIPPET_LENGTH && CharOperation.equals(TAG_SNIPPET, tagName)) {
+							this.tagValue = TAG_SNIPPET_LENGTH;
+							if (!this.inlineTagStarted) {
+								// @snippet is an inline comment
+								valid = false;
+							} else {
+								this.tagValue = TAG_SNIPPET_VALUE;
+								valid = parseSnippet();
+							}
 						} else {
 							this.tagValue = TAG_OTHERS_VALUE;
 							createTag();
@@ -805,6 +1089,189 @@
 	}
 
 	@Override
+	protected void pushSnippetText(int start, int end, boolean addNewLine, Object snippetTag) {
+
+		// Create text element
+		TextElement text = this.ast.newTextElement();
+		String textToBeAdded= new String( this.source, start, end-start);
+		int iindex = textToBeAdded.indexOf('*');
+		if (iindex > -1 && textToBeAdded.substring(0, iindex+1).trim().equals("*")) { //$NON-NLS-1$
+			textToBeAdded = textToBeAdded.substring(iindex+1);
+			if (addNewLine) {
+				textToBeAdded += System.lineSeparator();
+			}
+		}
+		text.setText(textToBeAdded);
+		text.setSourceRange(start, end-start);
+
+		// Search previous tag on which to add the text element
+		AbstractTagElement previousTag = null;
+		int previousStart = start;
+		if (this.astPtr == -1) {
+			previousTag = this.ast.newTagElement();
+			previousTag.setSourceRange(start, end-start);
+			pushOnAstStack(previousTag, true);
+		} else {
+			previousTag = (AbstractTagElement) this.astStack[this.astPtr];
+			previousStart = previousTag.getStartPosition();
+		}
+
+		AbstractTagElement prevTag = null;
+		// If we're in a inline tag, then retrieve previous tag in its fragments
+		List fragments = previousTag.fragments();
+		if (this.inlineTagStarted) {
+			int size = fragments.size();
+			if (size == 0) {
+				//do nothing
+			} else {
+				// If last fragment is a tag, then use it as previous tag
+				ASTNode lastFragment = (ASTNode) fragments.get(size-1);
+				if (lastFragment instanceof AbstractTagElement) {
+					previousTag = (AbstractTagElement) lastFragment;
+					previousStart = previousTag.getStartPosition();
+					if (this.snippetInlineTagStarted) {
+						fragments = previousTag.fragments();
+						size = fragments.size();
+						if (size == 0) {
+							//do nothing
+						} else {
+							lastFragment = (ASTNode) fragments.get(size-1);
+							if (lastFragment instanceof AbstractTagElement) {
+								prevTag = (AbstractTagElement) lastFragment;
+								this.snippetInlineTagStarted = false;
+							}
+						}
+						this.snippetInlineTagStarted = false;
+					}
+				}
+			}
+		}
+
+		int finEnd = end;
+		boolean isNotDummyJavaDocRegion = false;
+		if (prevTag instanceof JavaDocRegion && !((JavaDocRegion)prevTag).isDummyRegion()) {
+			isNotDummyJavaDocRegion = true;
+		}
+		// Add the text
+		if (prevTag != null && !isNotDummyJavaDocRegion) {
+
+			prevTag.fragments().add(text);
+			int curStart = prevTag.getStartPosition();
+			int curEnd = curStart + prevTag.getLength();
+			int finStart = start;
+			if (curStart <  start) {
+				finStart = curStart;
+			}
+			if (curEnd > end) {
+				finEnd = curEnd;
+			}
+			prevTag.setSourceRange(finStart, finEnd - finStart);
+		} else {
+			previousTag.fragments().add(text);
+		}
+		previousTag.setSourceRange(previousStart, finEnd-previousStart);
+		this.textStart = -1;
+
+		if (snippetTag instanceof TagElement) {
+			fragments =  ((TagElement) snippetTag).fragments();
+			for (Object frag : fragments) {
+				if (frag instanceof JavaDocRegion) {
+					JavaDocRegion region = (JavaDocRegion) frag;
+					if (!region.isDummyRegion() && !hasRegionEnded(region)) {
+						int startPos = region.getStartPosition();
+						int endPos = startPos + region.getLength();
+						if (startPos > start) {
+							startPos = start;
+						}
+						if (endPos < end) {
+							endPos = end;
+						}
+						Object textVal = region.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_REGION_TEXT);
+						if (!(textVal instanceof TextElement)) {
+							region.setProperty(TagProperty.TAG_PROPERTY_SNIPPET_REGION_TEXT, text);
+						}
+						region.setSourceRange(startPos, endPos-startPos);
+						if (isRegionToBeEnded(region)) {
+							setRegionEnded(region, true);
+						}
+					}
+				}
+			}
+		}
+	}
+
+	private boolean hasRegionEnded(JavaDocRegion region) {
+		boolean ended = false;
+		if (region != null) {
+			Object value = region.getProperty(JavaDocRegion.REGION_ENDED);
+			if (value instanceof Boolean && ((Boolean)value).booleanValue()) {
+				ended = true;
+			}
+		}
+		return ended;
+	}
+
+	private boolean isRegionToBeEnded(JavaDocRegion region) {
+		boolean toBeEnded = false;
+		if (region != null) {
+			Object value = region.getProperty(JavaDocRegion.REGION_TO_BE_ENDED);
+			if (value instanceof Boolean && ((Boolean)value).booleanValue()) {
+				toBeEnded = true;
+			}
+		}
+		return toBeEnded;
+	}
+
+	private void setRegionToBeEnded(JavaDocRegion region, boolean value) {
+		if (region != null) {
+			region.setProperty(JavaDocRegion.REGION_TO_BE_ENDED, value);
+		}
+	}
+
+	private void setRegionEnded(JavaDocRegion region, boolean value) {
+		if (region != null) {
+			region.setProperty(JavaDocRegion.REGION_ENDED, value);
+			setRegionToBeEnded(region, !value);
+		}
+	}
+
+	@Override
+	protected void pushExternalSnippetText(String text,int start, int end) {
+		String snippetLangHeader = "<pre>"; //$NON-NLS-1$ //the code snippets comes as preformatted so need to prefix them with <pre> tag
+		String snipperLangFooter = "</pre>"; //$NON-NLS-1$
+		text = snippetLangHeader + text + snipperLangFooter;
+		TextElement textElement = this.ast.newTextElement();
+		textElement.setText(text);
+		textElement.setSourceRange(start, end-start);
+
+		// Search previous tag on which to add the text element
+		TagElement previousTag = null;
+		int previousStart = start;
+		int previousEnd = end;
+		if (this.astPtr == -1) {
+			previousTag = this.ast.newTagElement();
+			previousTag.setSourceRange(start, end-start);
+			pushOnAstStack(previousTag, true);
+		} else {
+			previousTag = (TagElement) this.astStack[this.astPtr];
+			previousStart = previousTag.getStartPosition();
+			previousEnd = previousStart + previousTag.getLength();
+		}
+		previousTag.fragments().add(textElement);
+		int curStart = previousStart;
+		int curEnd = previousEnd;
+		if (start < previousStart) {
+			curStart = start;
+		}
+		if (end > previousEnd) {
+			curEnd = end;
+		}
+		previousTag.setSourceRange(curStart, curEnd-curStart);
+		this.textStart = -1;
+	}
+
+
+	@Override
 	protected boolean pushThrowName(Object typeRef) {
 		TagElement throwsTag = this.ast.newTagElement();
 		switch (this.tagValue) {
@@ -848,4 +1315,15 @@
 			this.docComment.tags().add(this.astStack[idx]);
 		}
 	}
+
+	@Override
+	protected boolean areRegionsClosed() {
+		// do nothing
+		return true;
+	}
+
+	@Override
+	protected void setRegionPosition(int currentPosition) {
+		// do nothing
+	}
 }
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/GuardedPattern.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/GuardedPattern.java
index dd0837f..18373d9 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/GuardedPattern.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/GuardedPattern.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2021 IBM Corporation and others.
+ * Copyright (c) 2021, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -36,7 +36,7 @@
 
 	GuardedPattern(AST ast) {
 		super(ast);
-		supportedOnlyIn17();
+		supportedOnlyIn18();
 		unsupportedWithoutPreviewError();
 	}
 
@@ -198,7 +198,7 @@
 	 * @return the expression node, or <code>null</code> if there is none
 	 */
 	public Expression getExpression() {
-		supportedOnlyIn17();
+		supportedOnlyIn18();
 		unsupportedWithoutPreviewError();
 		return this.conditonalExpression;
 	}
@@ -208,12 +208,12 @@
 	 * <code>empty</code> if there is none.
 	 * @return the pattern node
 	 * 			(element type: {@link Pattern})
-	 * @exception UnsupportedOperationException if this operation is used other than JLS17
+	 * @exception UnsupportedOperationException if this operation is used other than JLS18
 	 * @exception UnsupportedOperationException if this expression is used with previewEnabled flag as false
 	 * @noreference This method is not intended to be referenced by clients as it is a part of Java preview feature.
 	 */
 	public Pattern getPattern() {
-		supportedOnlyIn17();
+		supportedOnlyIn18();
 		unsupportedWithoutPreviewError();
 		return this.pattern;
 	}
@@ -232,7 +232,7 @@
 	 * </ul>
 	 */
 	public void setExpression(Expression expression) {
-		supportedOnlyIn17();
+		supportedOnlyIn18();
 		unsupportedWithoutPreviewError();
 		ASTNode oldChild = this.conditonalExpression;
 		preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
@@ -244,11 +244,11 @@
 	 * Sets the pattern of this switch case.
 	 * @param pattern
 	 * @noreference This method is not intended to be referenced by clients.
-	 * @exception UnsupportedOperationException if this operation is used not for JLS17
+	 * @exception UnsupportedOperationException if this operation is used not for JLS18
 	 * @exception UnsupportedOperationException if this operation is used without previewEnabled
 	 */
 	public void setPattern(Pattern pattern) {
-		supportedOnlyIn17();
+		supportedOnlyIn18();
 		unsupportedWithoutPreviewError();
 		ASTNode oldChild = this.pattern;
 		preReplaceChild(oldChild, pattern, PATTERN_PROPERTY);
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IDocElement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IDocElement.java
index a2e25bd..e39674d 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IDocElement.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IDocElement.java
@@ -22,8 +22,10 @@
  *   {@link MemberRef}
  *   {@link MethodRef}
  *   {@link Name}
+ *   {@link AbstractTagElement}
  *   {@link TagElement}
  *   {@link TextElement}
+ *   {@link JavaDocRegion}
  * </pre>
  *
  * @since 3.11, internal interface since 3.0
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/JavaDocRegion.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/JavaDocRegion.java
new file mode 100644
index 0000000..80c1e89
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/JavaDocRegion.java
@@ -0,0 +1,276 @@
+/*******************************************************************************
+ * Copyright (c) 2022 IBM Corporation 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
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jdt.internal.core.dom.util.DOMASTUtil;
+
+/**
+ * JavaDocRegion pattern AST node type.
+ *
+ * <pre>
+ * JavaDocRegion:
+ *     [ TagElement { <b>,</b> TagElement } ]
+ *     [ ASTNode { [TextElement] [JavaDocRegion] } ]
+ *     validSnippet
+ * </pre>
+ *
+ * @since 3.30
+ */
+
+@SuppressWarnings("rawtypes")
+public class JavaDocRegion extends AbstractTagElement{
+
+	JavaDocRegion(AST ast) {
+		super(ast);
+		unsupportedBelow18();
+	}
+
+	/**
+	 * The "tagName" structural property of this node type (type: {@link String}).
+	 */
+
+	public static final SimplePropertyDescriptor TAG_NAME_PROPERTY =
+			internalTagNamePropertyFactory(JavaDocRegion.class);
+	/**
+	 * The "fragments" structural property of this node type (element type: {@link IDocElement}).
+	 * These are the containers which will have texts and other JavaDoc regions
+	 */
+	public static final ChildListPropertyDescriptor FRAGMENTS_PROPERTY =
+			internalFragmentsPropertyFactory(JavaDocRegion.class);
+
+	/**
+	 * The "tags" structural property of this node type (child type: {@link TagElement}). (added in JEP 413).
+	 * These are the decorators like link, highlight etc
+	 */
+	public static final ChildListPropertyDescriptor TAGS_PROPERTY  =
+			new ChildListPropertyDescriptor(JavaDocRegion.class, "tags", TagElement.class, CYCLE_RISK); //$NON-NLS-1$);
+
+
+	/**
+	 * The "dummy regions" structural property of this node type (added in JEP 413).
+	 */
+	public static final SimplePropertyDescriptor DUMMY_REGION_PROPERTY  = new SimplePropertyDescriptor(JavaDocRegion.class, "dummyRegion", boolean.class, MANDATORY); //$NON-NLS-1$);
+
+	/**
+	 * The "validSnippet" structural property of this node type (added in JEP 413).
+	 */
+	public static final SimplePropertyDescriptor VALID_SNIPPET_PROPERTY  = new SimplePropertyDescriptor(JavaDocRegion.class, "validSnippet", boolean.class, MANDATORY); //$NON-NLS-1$);
+
+	static final String REGION_ENDED = "Region Ended"; //$NON-NLS-1$
+	static final String REGION_TO_BE_ENDED = "Region To Be Ended"; //$NON-NLS-1$
+
+	/**
+	 * A list of property descriptors (element type:
+	 * {@link StructuralPropertyDescriptor}),
+	 * or null if uninitialized.
+	 */
+	private static final List PROPERTY_DESCRIPTORS;
+
+	static {
+		List propertyList = new ArrayList(6);
+		createPropertyList(JavaDocRegion.class, propertyList);
+		addProperty(TAG_NAME_PROPERTY, propertyList);
+		addProperty(FRAGMENTS_PROPERTY, propertyList);
+		addProperty(TAGS_PROPERTY, propertyList);
+		addProperty(DUMMY_REGION_PROPERTY, propertyList);
+		addProperty(VALID_SNIPPET_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+	}
+
+	/**
+	 * The tags list; <code>empty</code> for none;
+	 */
+	private ASTNode.NodeList tags = new ASTNode.NodeList(TAGS_PROPERTY);
+
+	/**
+	 * The property dummyRegion
+	 */
+	private boolean dummyRegion = Boolean.TRUE;
+
+	/**
+	 * The property validSnippet
+	 */
+	private boolean validSnippet = Boolean.TRUE;
+
+
+
+
+	@Override
+	List internalStructuralPropertiesForType(int apiLevel) {
+		return propertyDescriptors(apiLevel);
+	}
+
+	@Override
+	final boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean newValue) {
+		if (property == DUMMY_REGION_PROPERTY) {
+			if (get) {
+				return isDummyRegion();
+			} else {
+				setDummyRegion(newValue);
+				return false;
+			}
+		} else if (property == VALID_SNIPPET_PROPERTY) {
+			if (get) {
+				return isValidSnippet();
+			} else {
+				setValidSnippet(newValue);
+				return false;
+			}
+		}
+		// allow default implementation to flag the error
+		return super.internalGetSetBooleanProperty(property, get, newValue);
+	}
+
+	@Override
+	final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+		if (property == FRAGMENTS_PROPERTY) {
+			return fragments();
+		} else if (property == TAGS_PROPERTY) {
+			return tags();
+		}
+		// allow default implementation to flag the error
+		return super.internalGetChildListProperty(property);
+	}
+
+	@Override
+	int getNodeType0() {
+		return JAVADOC_REGION;
+	}
+
+	@Override
+	boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+		return matcher.match(this, other);
+	}
+
+	@SuppressWarnings("unchecked")
+	@Override
+	ASTNode clone0(AST target) {
+		JavaDocRegion result = new JavaDocRegion(target);
+		result.setSourceRange(getStartPosition(), getLength());
+		result.setTagName(getTagName());
+		result.setDummyRegion(isDummyRegion());
+		result.setValidSnippet(isValidSnippet());
+		result.tags().addAll(
+				ASTNode.copySubtrees(target, tags()));
+		result.fragments().addAll(
+				ASTNode.copySubtrees(target, fragments()));
+		return result;
+	}
+
+	@Override
+	void accept0(ASTVisitor visitor) {
+		visitor.visit(this);
+		visitor.endVisit(this);
+
+	}
+
+	@Override
+	int memSize() {
+		return super.memSize() + 3*4 ;
+	}
+
+	@Override
+	int treeSize() {
+		return memSize() ;
+	}
+
+
+	/**
+	 * Returns a list of structural property descriptors for this node type.
+	 * Clients must not modify the result.
+	 *
+	 * @param apiLevel the API level; one of the
+	 * <code>AST.JLS*</code> constants
+
+	 * @return a list of property descriptors (element type:
+	 * {@link StructuralPropertyDescriptor})
+	 */
+	public static List propertyDescriptors(int apiLevel) {
+		if (DOMASTUtil.isJavaDocCodeSnippetSupported(apiLevel)) {
+			return PROPERTY_DESCRIPTORS;
+		}
+		return null;
+	}
+
+	/**
+	 * Returns the list of tag elements in this region, or
+	 * <code>empty</code> if there is none.
+	 *
+	 *  @return the list of tag element nodes
+	 *    (element type: {@link TagElement})
+	 * @exception UnsupportedOperationException if this operation is used below JLS18
+	 */
+	public List tags() {
+		unsupportedBelow18();
+		return this.tags;
+	}
+
+	/**
+	 * Returns <code>true</code> is region is dummy else <code>false</code>.
+	 * @return the dummyRegion
+	 * @exception UnsupportedOperationException if this operation is used below JLS18
+	 */
+	public boolean isDummyRegion() {
+		unsupportedBelow18();
+		return this.dummyRegion;
+	}
+
+	/**
+	 * Sets the value of dummyRegion property.
+	 * @param dummyRegion
+	 * @exception UnsupportedOperationException if this operation is used below JLS18
+	 */
+	public void setDummyRegion(boolean dummyRegion) {
+		unsupportedBelow18();
+		preValueChange(DUMMY_REGION_PROPERTY);
+		this.dummyRegion = dummyRegion;
+		postValueChange(DUMMY_REGION_PROPERTY);
+	}
+
+	/**
+	 * Returns <code>true</code> if region has valid snippet else <code>false</code>.
+	 * @return the validSnippet
+	 * @exception UnsupportedOperationException if this operation is used below JLS18
+	 */
+	public boolean isValidSnippet() {
+		unsupportedBelow18();
+		return this.validSnippet;
+	}
+
+	/**
+	 * Sets the value of validSnippet property.
+	 * @param validSnippet
+	 * @exception UnsupportedOperationException if this operation is used below JLS18
+	 */
+	public void setValidSnippet(boolean validSnippet) {
+		unsupportedBelow18();
+		preValueChange(VALID_SNIPPET_PROPERTY);
+		this.validSnippet = validSnippet;
+		postValueChange(VALID_SNIPPET_PROPERTY);
+	}
+
+	@Override
+	ChildListPropertyDescriptor internalFragmentsPropertyFactory() {
+		return FRAGMENTS_PROPERTY;
+	}
+
+	@Override
+	SimplePropertyDescriptor internalTagNamePropertyFactory() {
+		return TAG_NAME_PROPERTY;
+	}
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NullPattern.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NullPattern.java
index 293562c..4b8f83e 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NullPattern.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NullPattern.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2021 IBM Corporation and others.
+ * Copyright (c) 2021, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -64,6 +64,8 @@
 	 */
 	NullPattern(AST ast) {
 		super(ast);
+		supportedOnlyIn18();
+		unsupportedWithoutPreviewError();
 	}
 
 	@Override
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Pattern.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Pattern.java
index 0c8eb7b..e1bd074 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Pattern.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Pattern.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2021 IBM Corporation and others.
+ * Copyright (c) 2021, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -41,6 +41,9 @@
 	 */
 	Pattern(AST ast) {
 		super(ast);
+		supportedOnlyIn18();
+		unsupportedWithoutPreviewError();
+
 	}
 
 	/**
@@ -59,7 +62,7 @@
 	 *
 	 *  @return the list of pattern variables
 	 *    (element type: {@link SingleVariableDeclaration})
-	 * @exception UnsupportedOperationException if this operation is not used for JLS17
+	 * @exception UnsupportedOperationException if this operation is not used for JLS18
 	 * @exception UnsupportedOperationException if this operation is not used with previewEnabled flag as true
 	 * @noreference This method is not intended to be referenced by clients.
 	 */
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TagElement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TagElement.java
index 10aa5e7..94fbe6e 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TagElement.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TagElement.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2019 IBM Corporation and others.
+ * Copyright (c) 2004, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -17,6 +17,8 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.eclipse.jdt.internal.core.dom.util.DOMASTUtil;
+
 /**
  * AST node for a tag within a doc comment.
  * Tag elements nested within another tag element are called
@@ -24,6 +26,7 @@
  * <pre>
  * TagElement:
  *     [ <b>@</b> Identifier ] { DocElement }
+ *     {tagProperty = tagValue}
  * DocElement:
  *     TextElement
  *     Name
@@ -37,22 +40,29 @@
  * @noinstantiate This class is not intended to be instantiated by clients.
  */
 @SuppressWarnings({"rawtypes", "unchecked"})
-public final class TagElement extends ASTNode implements IDocElement {
+public final class TagElement extends AbstractTagElement {
+
 
 	/**
 	 * The "tagName" structural property of this node type (type: {@link String}).
-	 *
-	 * @since 3.0
 	 */
-	public static final SimplePropertyDescriptor TAG_NAME_PROPERTY =
-		new SimplePropertyDescriptor(TagElement.class, "tagName", String.class, OPTIONAL); //$NON-NLS-1$
 
+	public static final SimplePropertyDescriptor TAG_NAME_PROPERTY =
+			internalTagNamePropertyFactory(TagElement.class);
 	/**
 	 * The "fragments" structural property of this node type (element type: {@link IDocElement}).
-	 * @since 3.0
 	 */
 	public static final ChildListPropertyDescriptor FRAGMENTS_PROPERTY =
-		new ChildListPropertyDescriptor(TagElement.class, "fragments", IDocElement.class, CYCLE_RISK); //$NON-NLS-1$
+			internalFragmentsPropertyFactory(TagElement.class);
+
+	/**
+	 * The "properties" structural property of this node type (element type: {@link TagProperty}).
+	 * @since 3.30
+	 */
+	public static final ChildListPropertyDescriptor TAG_PROPERTIES_PROPERTY =
+		new ChildListPropertyDescriptor(TagElement.class, "tagProperties", TagProperty.class, CYCLE_RISK); //$NON-NLS-1$
+
+
 
 	/**
 	 * A list of property descriptors (element type:
@@ -62,12 +72,28 @@
 	 */
 	private static final List PROPERTY_DESCRIPTORS;
 
+	/**
+	 * A list of property descriptors (element type:
+	 * {@link StructuralPropertyDescriptor}),
+	 * or null if uninitialized.
+	 * @since 3.30
+	 */
+	private static final List PROPERTY_DESCRIPTORS_18;
+
 	static {
 		List propertyList = new ArrayList(3);
 		createPropertyList(TagElement.class, propertyList);
 		addProperty(TAG_NAME_PROPERTY, propertyList);
 		addProperty(FRAGMENTS_PROPERTY, propertyList);
 		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+
+		propertyList = new ArrayList(4);
+		createPropertyList(TagElement.class, propertyList);
+		addProperty(TAG_NAME_PROPERTY, propertyList);
+		addProperty(FRAGMENTS_PROPERTY, propertyList);
+		addProperty(TAG_PROPERTIES_PROPERTY, propertyList);
+
+		PROPERTY_DESCRIPTORS_18 = reapPropertyList(propertyList);
 	}
 
 	/**
@@ -81,8 +107,19 @@
 	 * @since 3.0
 	 */
 	public static List propertyDescriptors(int apiLevel) {
+		if (DOMASTUtil.isJavaDocCodeSnippetSupported(apiLevel)) {
+			return PROPERTY_DESCRIPTORS_18;
+		}
 		return PROPERTY_DESCRIPTORS;
 	}
+	@Override
+	final ChildListPropertyDescriptor internalFragmentsPropertyFactory() {
+		return FRAGMENTS_PROPERTY;
+	}
+	@Override
+	final SimplePropertyDescriptor internalTagNamePropertyFactory() {
+		return TAG_NAME_PROPERTY;
+	}
 
 	/**
 	 * Standard doc tag name (value {@value}).
@@ -94,12 +131,13 @@
 	 * <p>
 	 * Note that this tag first appeared in J2SE 5.
 	 * </p>
-	 * @since 3.1
+	 * @since 3.30
 	 */
 	public static final String TAG_CODE = "@code"; //$NON-NLS-1$
 
 	/**
 	 * Standard doc tag name (value {@value}).
+	 * @since 3.30
 	 */
 	public static final String TAG_DEPRECATED = "@deprecated"; //$NON-NLS-1$
 
@@ -110,33 +148,37 @@
 
 	/**
 	 * Standard doc tag name (value {@value}).
+	 * @since 3.30
 	 */
 	public static final String TAG_EXCEPTION = "@exception"; //$NON-NLS-1$
 
 	/**
 	 * Standard doc tag name (value {@value}).
-	 * @since 3.18
+	 * @since 3.30
 	 */
 	public static final String TAG_HIDDEN = "@hidden"; //$NON-NLS-1$
 
 	/**
 	 * Standard doc tag name (value {@value}).
-	 * @since 3.18
+	 * @since 3.30
 	 */
 	public static final String TAG_INDEX = "@index"; //$NON-NLS-1$
 
 	/**
 	 * Standard inline doc tag name (value {@value}).
+	 * @since 3.30
 	 */
 	public static final String TAG_INHERITDOC = "@inheritDoc"; //$NON-NLS-1$
 
 	/**
 	 * Standard inline doc tag name (value {@value}).
+	 * @since 3.30
 	 */
 	public static final String TAG_LINK = "@link"; //$NON-NLS-1$
 
 	/**
 	 * Standard inline doc tag name (value {@value}).
+	 * @since 3.30
 	 */
 	public static final String TAG_LINKPLAIN = "@linkplain"; //$NON-NLS-1$
 
@@ -145,43 +187,49 @@
 	 * <p>
 	 * Note that this tag first appeared in J2SE 5.
 	 * </p>
-	 * @since 3.1
+	 * @since 3.30
 	 */
 	public static final String TAG_LITERAL = "@literal"; //$NON-NLS-1$
 
 	/**
 	 * Standard doc tag name (value {@value}).
+	 * @since 3.30
 	 */
 	public static final String TAG_PARAM = "@param"; //$NON-NLS-1$
 
 	/**
 	 * Standard doc tag name (value {@value}).
-	 * @since 3.18
+	 * @since 3.30
 	 */
 	public static final String TAG_PROVIDES = "@provides"; //$NON-NLS-1$
 
 	/**
 	 * Standard doc tag name (value {@value}).
+	 * @since 3.30
 	 */
 	public static final String TAG_RETURN = "@return"; //$NON-NLS-1$
 
 	/**
 	 * Standard doc tag name (value {@value}).
+	 * @since 3.30
 	 */
 	public static final String TAG_SEE = "@see"; //$NON-NLS-1$
 
 	/**
 	 * Standard doc tag name (value {@value}).
+	 * @since 3.30
 	 */
 	public static final String TAG_SERIAL = "@serial"; //$NON-NLS-1$
 
 	/**
 	 * Standard doc tag name (value {@value}).
+	 * @since 3.30
 	 */
 	public static final String TAG_SERIALDATA= "@serialData"; //$NON-NLS-1$
 
 	/**
 	 * Standard doc tag name (value {@value}).
+	 * @since 3.30
 	 */
 	public static final String TAG_SERIALFIELD= "@serialField"; //$NON-NLS-1$
 
@@ -192,60 +240,76 @@
 
 	/**
 	 * Standard doc tag name (value {@value}).
-	 * @since 3.18
+	 * @since 3.30
 	 */
 	public static final String TAG_SUMMARY = "@summary"; //$NON-NLS-1$
 
 	/**
 	 * Standard doc tag name (value {@value}).
+	 * @since 3.30
 	 */
 	public static final String TAG_THROWS = "@throws"; //$NON-NLS-1$
 
 	/**
 	 * Standard doc tag name (value {@value}).
-	 * @since 3.18
+	 * @since 3.30
 	 */
 	public static final String TAG_USES = "@uses"; //$NON-NLS-1$
 
 	/**
 	 * Standard inline doc tag name (value {@value}).
+	 * @since 3.30
 	 */
 	public static final String TAG_VALUE= "@value"; //$NON-NLS-1$
 
 	/**
 	 * Standard doc tag name (value {@value}).
+	 * @since 3.30
 	 */
 	public static final String TAG_VERSION = "@version"; //$NON-NLS-1$
 
 	/**
 	 * Javadoc tag name (value {@value}).
-	 * @since 3.18
+	 * @since 3.30
 	 */
 	public static final String TAG_API_NOTE = "@apiNote"; //$NON-NLS-1$
 
 	/**
 	 * Javadoc tag name (value {@value}).
-	 * @since 3.18
+	 * @since 3.30
 	 */
 	public static final String TAG_IMPL_SPEC = "@implSpec"; //$NON-NLS-1$
 
 	/**
 	 * Javadoc tag name (value {@value}).
-	 * @since 3.18
+	 * @since 3.30
 	 */
 	public static final String TAG_IMPL_NOTE = "@implNote"; //$NON-NLS-1$
 
 	/**
-	 * The tag name, or null if none; defaults to null.
+	 * Standard inline doc tag name (value {@value}).
+	 * @since 3.30
 	 */
-	private String optionalTagName = null;
+	public static final String TAG_SNIPPET = "@snippet"; //$NON-NLS-1$
 
 	/**
-	 * The list of doc elements (element type: {@link IDocElement}).
+	 * Standard snippet doc tag name (value {@value}).
+	 * @since 3.30
+	 */
+	public static final String TAG_HIGHLIGHT = "@highlight"; //$NON-NLS-1$
+
+	/**
+	 * Standard snippet doc tag name (value {@value}).
+	 * @since 3.30
+	 */
+	public static final String TAG_REPLACE = "@replace"; //$NON-NLS-1$
+
+	/**
+	 * The list of doc elements (element type: {@link TagProperty}).
 	 * Defaults to an empty list.
 	 */
-	private ASTNode.NodeList fragments =
-		new ASTNode.NodeList(FRAGMENTS_PROPERTY);
+	private ASTNode.NodeList tagProperties =
+		new ASTNode.NodeList(TAG_PROPERTIES_PROPERTY);
 
 	/**
 	 * Creates a new AST node for a tag element owned by the given AST.
@@ -267,24 +331,13 @@
 		return propertyDescriptors(apiLevel);
 	}
 
-	@Override
-	final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
-		if (property == TAG_NAME_PROPERTY) {
-			if (get) {
-				return getTagName();
-			} else {
-				setTagName((String) value);
-				return null;
-			}
-		}
-		// allow default implementation to flag the error
-		return super.internalGetSetObjectProperty(property, get, value);
-	}
 
 	@Override
 	final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
 		if (property == FRAGMENTS_PROPERTY) {
 			return fragments();
+		} else if (property == TAG_PROPERTIES_PROPERTY) {
+			return tagProperties();
 		}
 		// allow default implementation to flag the error
 		return super.internalGetChildListProperty(property);
@@ -301,6 +354,9 @@
 		result.setSourceRange(getStartPosition(), getLength());
 		result.setTagName(getTagName());
 		result.fragments().addAll(ASTNode.copySubtrees(target, fragments()));
+		if (DOMASTUtil.isJavaDocCodeSnippetSupported(target.apiLevel)) {
+			result.tagProperties().addAll(ASTNode.copySubtrees(target, tagProperties()));
+		}
 		return result;
 	}
 
@@ -315,119 +371,113 @@
 		boolean visitChildren = visitor.visit(this);
 		if (visitChildren) {
 			acceptChildren(visitor, this.fragments);
+			if (DOMASTUtil.isJavaDocCodeSnippetSupported(this.getAST().apiLevel)) {
+				acceptChildren(visitor, this.tagProperties);
+			}
 		}
 		visitor.endVisit(this);
 	}
 
 	/**
-	 * Returns this node's tag name, or <code>null</code> if none.
-	 * For top level doc tags such as parameter tags, the tag name
-     * includes the "@" character ("@param").
-	 * For inline doc tags such as link tags, the tag name
-     * includes the "@" character ("@link").
-     * The tag name may also be <code>null</code>; this is used to
-     * represent the material at the start of a doc comment preceding
-     * the first explicit tag.
-     *
-	 * @return the tag name, or <code>null</code> if none
+	 * Returns the live list of tag properties in this tag element.
+	 *
+	 * @return the live list of properties in this tag element
+	 * (element type: {@link TagProperty})
+	 * @exception UnsupportedOperationException if this operation is used less than JLS18
+	 * @since 3.30
 	 */
-	public String getTagName() {
-		return this.optionalTagName;
+	public List tagProperties() {
+		unsupportedBelow18();
+		return this.tagProperties;
 	}
 
 	/**
-	 * Sets the tag name of this node to the given value.
-	 * For top level doc tags such as parameter tags, the tag name
-	 * includes the "@" character ("@param").
-	 * For inline doc tags such as link tags, the tag name
-	 * includes the "@" character ("@link").
-	 * The tag name may also be <code>null</code>; this is used to
-	 * represent the material at the start of a doc comment preceding
-	 * the first explicit tag.
+	 * Returns the list of non dummy JavaDopRegions in this tag element.
 	 *
-	 * @param tagName the tag name, or <code>null</code> if none
+	 * @return the list of non dummy JavaDopRegions in this tag element.
+	 * (element type: {@link JavaDocRegion})
+	 * @exception UnsupportedOperationException if this operation is used less than JLS18
+	 * @since 3.30
 	 */
-	public void setTagName(String tagName) {
-		preValueChange(TAG_NAME_PROPERTY);
-		this.optionalTagName = tagName;
-		postValueChange(TAG_NAME_PROPERTY);
+	public List tagRegions() {
+		unsupportedBelow18();
+		List<JavaDocRegion> regions = new ArrayList<>();
+		List<Object> frags = this.fragments();
+		if ( frags != null) {
+			for (Object fragment : frags) {
+				if (fragment instanceof JavaDocRegion
+						&& !((JavaDocRegion)fragment).isDummyRegion()) {
+					regions.add((JavaDocRegion)fragment);
+				}
+			}
+		}
+		return regions;
 	}
 
 	/**
-	 * Returns the live list of fragments in this tag element.
-	 * <p>
-	 * The fragments cover everything following the tag name
-	 * (or everything if there is no tag name), and generally omit
-	 * embedded line breaks (and leading whitespace on new lines,
-	 * including any leading "*"). {@link org.eclipse.jdt.core.dom.TagElement}
-	 * nodes are used to represent tag elements (e.g., "@link")
-	 * nested within this tag element.
-	 * </p>
-	 * <p>
-	 * Here are some typical examples:
-	 * <ul>
-	 * <li>"@see Foo#bar()" - TagElement with tag name "@see";
-	 * fragments() contains a single MethodRef node</li>
-	 * <li>"@param args the program arguments" -
-	 * TagElement with tag name "@param";
-	 * 2 fragments: SimpleName ("args"), TextElement
-	 * (" the program arguments")</li>
-	 * <li>"@return See {&#64;link #foo foo} instead." -
-	 * TagElement with tag name "@return";
-	 * 3 fragments: TextElement ("See "),
-	 * TagElement (for "&#64;link #foo foo"),
-	 * TextElement (" instead.")</li>
-	 * </ul>
-	 * The use of Name, MethodRef, and MemberRef nodes within
-	 * tag elements allows these fragments to be queried for
-	 * binding information.
-	 * <p>
-	 * Adding and removing nodes from this list affects this node
-	 * dynamically. The nodes in this list may be of various
-	 * types, including {@link TextElement},
-	 * {@link org.eclipse.jdt.core.dom.TagElement}, {@link Name},
-	 * {@link MemberRef}, and {@link MethodRef}.
-	 * Clients should assume that the list of types may grow in
-	 * the future, and write their code to deal with unexpected
-	 * nodes types. However, attempts to add a non-proscribed type
-	 * of node will trigger an exception.
+	 * Returns the list of non dummy JavaDocRegions containing this ASTNode and IDocElement.
 	 *
-	 * @return the live list of doc elements in this tag element
-	 * (element type: {@link IDocElement})
+	 * @return the list of non dummy JavaDocRegions containing this ASTNode and IDocElement.
+	 * (element type: {@link JavaDocRegion})
+	 * @exception UnsupportedOperationException if this operation is used less than JLS18
+	 * @since 3.30
 	 */
-	public List fragments() {
-		return this.fragments;
+	public List tagRegionsContainingTextElement(ASTNode docElem) {
+		unsupportedBelow18();
+		List<JavaDocRegion> regions = new ArrayList<>();
+		if (docElem == null || !(docElem instanceof IDocElement)) {
+			return regions;
+		} else {
+			int textElemStart = docElem.getStartPosition();
+			int textElemEnd = textElemStart + docElem.getLength();
+			List<JavaDocRegion> javaDocRegions = this.tagRegions();
+			for (JavaDocRegion region : javaDocRegions) {
+				int regionStart = region.getStartPosition();
+				int regionEnd = regionStart + region.getLength();
+				if (regionStart <= textElemStart && regionEnd >= textElemEnd) {
+					regions.add(region);
+				}
+			}
+		}
+		return regions;
 	}
 
 	/**
-	 * Returns whether this tag element is nested within another
-	 * tag element. Nested tag elements appears enclosed in
-	 * "{" and "}"; certain doc tags, including "@link" and
-	 * "@linkplain" are only meaningful as nested tags.
-	 * Top-level (i.e., non-nested) doc tags begin on a new line;
-	 * certain doc tags, including "@param" and
-	 * "@see" are only meaningful as top-level tags.
-	 * <p>
-	 * This convenience methods checks to see whether the parent
-	 * of this node is of type {@link org.eclipse.jdt.core.dom.TagElement}.
-	 * </p>
+	 * Returns the list of non dummy JavaDocRegions starting at this ASTNode and IDocElement.
 	 *
-	 * @return <code>true</code> if this node is a nested tag element,
-	 * and false if this node is either parented by a doc comment node
-	 * ({@link Javadoc}), or is unparented
+	 * @return the list of non dummy JavaDocRegions starting at this ASTNode and IDocElement.
+	 * (element type: {@link JavaDocRegion})
+	 * @exception UnsupportedOperationException if this operation is used less than JLS18
+	 * @since 3.30
 	 */
-	public boolean isNested() {
-		return (getParent() instanceof TagElement);
+	public List tagRegionsStartingAtTextElement(ASTNode docElem) {
+		unsupportedBelow18();
+		List<JavaDocRegion> regions = new ArrayList<>();
+		if (docElem == null || !(docElem instanceof TextElement)) {
+			return regions;
+		} else {
+			TextElement textElem= (TextElement) docElem;
+			List<JavaDocRegion> javaDocRegions = this.tagRegions();
+			for (JavaDocRegion region : javaDocRegions) {
+				if (!region.isDummyRegion()) {
+					Object textObj= region.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_REGION_TEXT);
+					if (textElem.equals(textObj)) {
+						regions.add(region);
+					}
+				}
+			}
+		}
+		return regions;
 	}
 
 	@Override
 	int memSize() {
-		int size = BASE_NODE_SIZE + 2 * 4 + stringSize(this.optionalTagName);
-		return size;
+		return super.memSize();
 	}
 
 	@Override
 	int treeSize() {
-		return memSize() + this.fragments.listSize();
+		return memSize() + (DOMASTUtil.isJavaDocCodeSnippetSupported(this.getAST().apiLevel)? this.tagProperties.listSize(): 0);
 	}
+
 }
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TagProperty.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TagProperty.java
new file mode 100644
index 0000000..fd7b913
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TagProperty.java
@@ -0,0 +1,278 @@
+/*******************************************************************************
+ * Copyright (c) 2022 IBM Corporation 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
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jdt.internal.core.dom.util.DOMASTUtil;
+
+/**
+ * TagProperty pattern AST node type.
+ *
+ * <pre>
+ * TagProperty:
+ *      Name
+ *      String Value
+ *      Node Value
+ * </pre>
+ *
+ * @since 3.30
+ */
+
+@SuppressWarnings("rawtypes")
+public class TagProperty extends ASTNode implements IDocElement{
+
+	TagProperty(AST ast) {
+		super(ast);
+		unsupportedBelow18();
+	}
+
+	/**
+	 * The "name" structural property of this node type (added in JEP 413).
+	 */
+	public static final SimplePropertyDescriptor NAME_PROPERTY  = new SimplePropertyDescriptor(TagProperty.class, "name", String.class, MANDATORY); //$NON-NLS-1$);
+
+	/**
+	 * The "string_value" structural property of this node type . (added in JEP 413).
+	 */
+	public static final SimplePropertyDescriptor STRING_VALUE_PROPERTY  =
+			new SimplePropertyDescriptor(TagProperty.class, "string_value", String.class, MANDATORY); //$NON-NLS-1$);
+
+	/**
+	 * The "node_value" structural property of this node type . (added in JEP 413).
+	 */
+	public static final ChildPropertyDescriptor NODE_VALUE_PROPERTY  =
+			new ChildPropertyDescriptor(TagProperty.class, "node_value", ASTNode.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$);
+
+	public static final String TAG_PROPERTY_SNIPPET_IS_VALID = "IsSnippetValid"; //$NON-NLS-1$
+
+	public static final String TAG_PROPERTY_SNIPPET_ERROR = "SnippetError"; //$NON-NLS-1$
+
+	/**
+	 * @since 3.30
+	 */
+	public static final String TAG_PROPERTY_SNIPPET_ID =  "SnippetID"; //$NON-NLS-1$
+
+	/**
+	 * @since 3.30
+	 */
+	public static final String TAG_PROPERTY_SNIPPET_INLINE_TAG_COUNT = "SnippetInlineTagCount"; //$NON-NLS-1$
+
+	/**
+	 * @since 3.30
+	 */
+	public static final String TAG_PROPERTY_SNIPPET_REGION_TEXT = "SnippetRegionTextElement"; //$NON-NLS-1$
+
+	/**
+	 * A list of property descriptors (element type:
+	 * {@link StructuralPropertyDescriptor}),
+	 * or null if uninitialized.
+	 */
+	private static final List PROPERTY_DESCRIPTORS;
+
+
+
+	static {
+		List propertyList = new ArrayList(4);
+		createPropertyList(TagProperty.class, propertyList);
+		addProperty(NAME_PROPERTY, propertyList);
+		addProperty(STRING_VALUE_PROPERTY, propertyList);
+		addProperty(NODE_VALUE_PROPERTY, propertyList);
+		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+	}
+
+	/**
+	 * The property name
+	 */
+	private String name = null;
+
+	/**
+	 * The property string value
+	 */
+	private String string_value = null;
+
+	/**
+	 * The property node value
+	 */
+	private ASTNode node_value = null;
+
+
+
+
+	@Override
+	List internalStructuralPropertiesForType(int apiLevel) {
+		return propertyDescriptors(apiLevel);
+	}
+
+
+	@Override
+	final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object newValue) {
+		if (property == NAME_PROPERTY) {
+			if (get) {
+				return getName();
+			} else {
+				setName((String)newValue);
+				return null;
+			}
+		} else if (property == STRING_VALUE_PROPERTY) {
+			if (get) {
+				return getStringValue();
+			} else {
+				setStringValue((String)newValue);
+				return null;
+			}
+		}
+		// allow default implementation to flag the error
+		return super.internalGetSetObjectProperty(property, get, newValue);
+	}
+
+	@Override
+	final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+		if (property == NODE_VALUE_PROPERTY) {
+			if (get) {
+				return getNodeValue();
+			} else {
+				setNodeValue(child);
+				return null;
+			}
+		}
+		// allow default implementation to flag the error
+		return super.internalGetSetChildProperty(property, get, child);
+	}
+
+	@Override
+	int getNodeType0() {
+		return TAG_PROPERTY;
+	}
+
+	@Override
+	boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+		return matcher.match(this, other);
+	}
+
+	@Override
+	ASTNode clone0(AST target) {
+		TagProperty result = new TagProperty(target);
+		result.setSourceRange(getStartPosition(), getLength());
+		result.setName(getName());
+		result.setStringValue(getStringValue());
+		result.setNodeValue(ASTNode.copySubtree(target, getNodeValue()));
+		return result;
+	}
+
+	@Override
+	void accept0(ASTVisitor visitor) {
+		visitor.visit(this);
+		visitor.endVisit(this);
+
+	}
+
+	@Override
+	int memSize() {
+		return BASE_NODE_SIZE + 1 * 4 + stringSize(this.name) + stringSize(this.string_value);
+	}
+
+	@Override
+	int treeSize() {
+		return memSize();
+	}
+
+
+	/**
+	 * Returns a list of structural property descriptors for this node type.
+	 * Clients must not modify the result.
+	 *
+	 * @param apiLevel the API level; one of the
+	 * <code>AST.JLS*</code> constants
+
+	 * @return a list of property descriptors (element type:
+	 * {@link StructuralPropertyDescriptor})
+	 */
+	public static List propertyDescriptors(int apiLevel) {
+		if (DOMASTUtil.isJavaDocCodeSnippetSupported(apiLevel)) {
+			return PROPERTY_DESCRIPTORS;
+		}
+		return null;
+	}
+
+	/**
+	 * Returns the name of this tag property.
+	 * @return the name
+	 * @exception UnsupportedOperationException if this operation is used below than JLS18
+	 */
+	public String getName() {
+		unsupportedBelow18();
+		return this.name;
+	}
+
+	/**
+	 * Returns the string value of this tag property.
+	 * @return the string_value
+	 * @exception UnsupportedOperationException if this operation is used below than JLS18
+	 */
+	public String getStringValue() {
+		unsupportedBelow18();
+		return this.string_value;
+	}
+
+	/**
+	 * Returns the node value of this tag property.
+	 * @return the node_value
+	 * @exception UnsupportedOperationException if this operation is used below than JLS18
+	 */
+	public ASTNode getNodeValue() {
+		unsupportedBelow18();
+		return this.node_value;
+	}
+
+	/**
+	 * Sets the name of this tag property.
+	 *
+	 * @param name
+	 * @exception UnsupportedOperationException if this operation is used below JLS18
+	 */
+	public void setName(String name) {
+		unsupportedBelow18();
+		preValueChange(NAME_PROPERTY);
+		this.name = name;
+		postValueChange(NAME_PROPERTY);
+	}
+
+	/**
+	 * Sets the string value of this tag property.
+	 * @param value
+	 * @exception UnsupportedOperationException if this operation is used below JLS18
+	 */
+	public void setStringValue(String value) {
+		unsupportedBelow18();
+		preValueChange(STRING_VALUE_PROPERTY);
+		this.string_value = value;
+		postValueChange(STRING_VALUE_PROPERTY);
+	}
+
+	/**
+	 * Sets the node value of this tag property.
+	 * @param value
+	 * @exception UnsupportedOperationException if this operation is used below JLS18
+	 */
+	public void setNodeValue(ASTNode value) {
+		unsupportedBelow18();
+		ASTNode oldChild = this.node_value;
+		preReplaceChild(oldChild, value, NODE_VALUE_PROPERTY);
+		this.node_value = value;
+		postReplaceChild(oldChild, value, NODE_VALUE_PROPERTY);
+	}
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypePattern.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypePattern.java
index 7990584..135024e 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypePattern.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypePattern.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2021 IBM Corporation and others.
+ * Copyright (c) 2021, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -60,7 +60,7 @@
 
 	TypePattern(AST ast) {
 		super(ast);
-		supportedOnlyIn17();
+		supportedOnlyIn18();
 		unsupportedWithoutPreviewError();
 	}
 
@@ -123,7 +123,7 @@
 
 	@Override
 	public List<SingleVariableDeclaration> patternVariables() {
-		supportedOnlyIn17();
+		supportedOnlyIn18();
 		unsupportedWithoutPreviewError();
 		return new ArrayList<SingleVariableDeclaration>(Arrays.asList(getPatternVariable()));
 	}
@@ -138,12 +138,12 @@
 	 * <li>the node already has a parent</li>
 	 * <li>a cycle in would be created</li>
 	 * </ul>
-	 * @exception UnsupportedOperationException if this operation is used other than JLS17
+	 * @exception UnsupportedOperationException if this operation is used other than JLS18
 	 * @exception UnsupportedOperationException if this expression is used with previewEnabled flag as false
 	 * @noreference This method is not intended to be referenced by clients as it is a part of Java preview feature.
 	 */
 	public void setPatternVariable(SingleVariableDeclaration patternVariable) {
-		supportedOnlyIn17();
+		supportedOnlyIn18();
 		unsupportedWithoutPreviewError();
 		if (patternVariable == null) {
 			throw new IllegalArgumentException();
@@ -158,12 +158,12 @@
 	 * Returns the pattern variable of Types Pattern.
 	 *
 	 * @return the pattern variable
-	 * @exception UnsupportedOperationException if this operation is used other than JLS17
+	 * @exception UnsupportedOperationException if this operation is used other than JLS18
 	 * @exception UnsupportedOperationException if this expression is used with previewEnabled flag as false
 	 * @noreference This method is not intended to be referenced by clients as it is a part of Java preview feature.
 	 */
 	public SingleVariableDeclaration getPatternVariable() {
-		supportedOnlyIn17();
+		supportedOnlyIn18();
 		unsupportedWithoutPreviewError();
 		if (this.patternVariable  == null) {
 			// lazy init must be thread-safe for readers
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/NaiveASTFlattener.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/NaiveASTFlattener.java
index 1a9f6e6..e9266e2 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/NaiveASTFlattener.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/NaiveASTFlattener.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2021 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -7,6 +7,7 @@
  * https://www.eclipse.org/legal/epl-2.0/
  *
  * SPDX-License-Identifier: EPL-2.0
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Fraunhofer FIRST - extended API and implementation
@@ -937,6 +938,12 @@
 	}
 
 	@Override
+	public boolean visit(JavaDocRegion node) {
+		//ToDO
+		return false;
+	}
+
+	@Override
 	public boolean visit(LabeledStatement node) {
 		printIndent();
 		node.getLabel().accept(this);
@@ -1744,6 +1751,13 @@
 			e.accept(this);
 			previousRequiresWhiteSpace = !currentIncludesWhiteSpace && !(e instanceof TagElement);
 		}
+		if (DOMASTUtil.isJavaDocCodeSnippetSupported(node.getAST().apiLevel())) {
+			for (Iterator it = node.tagProperties().iterator(); it.hasNext(); ) {
+				TagProperty tagProperty = (TagProperty) it.next();
+				tagProperty.accept(this);
+			}
+
+		}
 		if (node.isNested()) {
 			this.buffer.append("}");//$NON-NLS-1$
 		}
@@ -1751,6 +1765,19 @@
 	}
 
 	@Override
+	public boolean visit(TagProperty node) {
+		this.buffer.append("\n{"); //$NON-NLS-1$
+		this.buffer.append(node.getName());
+		this.buffer.append(" = "); //$NON-NLS-1$
+		this.buffer.append(node.getStringValue());
+		node.getNodeValue().accept(this);
+		this.buffer.append("}"); //$NON-NLS-1$
+		return false;
+	}
+
+
+
+	@Override
 	public boolean visit(TextBlock node) {
 		this.buffer.append(node.getEscapedValue());
 		return false;
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/util/DOMASTUtil.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/util/DOMASTUtil.java
index 625c426..9cc4659 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/util/DOMASTUtil.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/util/DOMASTUtil.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2019, 2021 IBM Corporation and others.
+ * Copyright (c) 2019, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -19,6 +19,7 @@
 import org.eclipse.jdt.core.dom.ASTNode;
 import org.eclipse.jdt.core.dom.Modifier;
 
+@SuppressWarnings("deprecation")
 public class DOMASTUtil {
 
 	/**
@@ -54,7 +55,6 @@
 	 * @see ASTNode#getNodeType()
 	 * @since 3.22
 	 */
-	@SuppressWarnings("deprecation")
 	private static boolean isNodeTypeSupportedinAST(int apiLevel, boolean previewEnabled, int nodeType) {
 		switch (nodeType) {
 			case ASTNode.SWITCH_EXPRESSION:
@@ -67,6 +67,8 @@
 				return apiLevel >= AST.JLS16;
 			case ASTNode.TYPE_PATTERN:
 				return apiLevel == AST.getJLSLatest() && previewEnabled;
+			case ASTNode.TAG_PROPERTY:
+				return apiLevel >= AST.JLS18;
 		}
 		return false;
 	}
@@ -181,7 +183,11 @@
 		return isNodeTypeSupportedinAST(apiLevel, previewEnabled, ASTNode.TYPE_PATTERN);
 	}
 
-	@SuppressWarnings("deprecation")
+	public static boolean isJavaDocCodeSnippetSupported(int apiLevel) {
+		return isNodeTypeSupportedinAST(apiLevel, true, ASTNode.TAG_PROPERTY);
+	}
+
+
 	public static void checkASTLevel(int level) {
 		// Clients can use AST.getJLSLatest()
 		if(level >=AST.JLS8 && level <= AST.getJLSLatest() )
@@ -197,7 +203,7 @@
 
 	private static final String[] AST_COMPLIANCE_MAP = {"-1","-1",JavaCore.VERSION_1_2, JavaCore.VERSION_1_3, JavaCore.VERSION_1_7, //$NON-NLS-1$ //$NON-NLS-2$
 			JavaCore.VERSION_1_7, JavaCore.VERSION_1_7, JavaCore.VERSION_1_7, JavaCore.VERSION_1_8, JavaCore.VERSION_9, JavaCore.VERSION_10,
-			JavaCore.VERSION_11, JavaCore.VERSION_12, JavaCore.VERSION_13, JavaCore.VERSION_14, JavaCore.VERSION_15, JavaCore.VERSION_16, JavaCore.VERSION_17};
+			JavaCore.VERSION_11, JavaCore.VERSION_12, JavaCore.VERSION_13, JavaCore.VERSION_14, JavaCore.VERSION_15, JavaCore.VERSION_16, JavaCore.VERSION_17, JavaCore.VERSION_18};
 
 	/**
 	 * Calculates the JavaCore Option value string corresponding to the input ast level.
@@ -206,7 +212,6 @@
 	 * @param astLevel
 	 * @return JavaCore Option value string corresponding to the ast level
 	 */
-	@SuppressWarnings("deprecation")
 	public static String getCompliance(int astLevel) {
 		if (astLevel < AST.JLS2 && astLevel > AST.getJLSLatest()) return JavaCore.latestSupportedJavaVersion();
 		return AST_COMPLIANCE_MAP[astLevel];
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CommentsPreparator.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CommentsPreparator.java
index bf2625a..afea0a4 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CommentsPreparator.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CommentsPreparator.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2014, 2020 Mateusz Matela and others.
+ * Copyright (c) 2014, 2022 Mateusz Matela and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -106,8 +106,8 @@
 	/** Index: position within current comment; Value: whether wrapping on special characters is allowed */
 	private boolean[] allowSubstituteWrapping;
 
-	private int noFormatTagOpenStart = -1;
-	private int formatCodeTagOpenEnd = -1;
+	private int noFormatOpenTagStartIndex = -1;
+	private int formatCodeOpenTagEndIndex = -1;
 	private int lastFormatCodeClosingTagIndex = -1;
 	private ArrayList<Integer> commonAttributeAnnotations = new ArrayList<Integer>();
 	private DefaultCodeFormatter commentCodeFormatter;
@@ -538,8 +538,8 @@
 
 	@Override
 	public boolean visit(Javadoc node) {
-		this.noFormatTagOpenStart = -1;
-		this.formatCodeTagOpenEnd = -1;
+		this.noFormatOpenTagStartIndex = -1;
+		this.formatCodeOpenTagEndIndex = -1;
 		this.lastFormatCodeClosingTagIndex = -1;
 		this.commonAttributeAnnotations.clear();
 		this.ctm = null;
@@ -602,6 +602,7 @@
 				startTokeen.breakBefore();
 
 			handleHtml(node);
+			this.ctm.get(tokenStartingAt(node.getStartPosition())).setToEscape(false);
 		}
 
 		if (node.isNested() && IMMUTABLE_TAGS.contains(tagName) && startIndex < endIndex) {
@@ -779,7 +780,7 @@
 				continue;
 
 			if (matcher.start(2) < matcher.end(2)) {
-				handleFormatCodeTag(startPos, endPos, isOpeningTag);
+				handleFormatCodeTag(node, startPos, endPos, isOpeningTag);
 			}
 			if (this.options.comment_format_html) {
 				if (TagElement.TAG_PARAM.equals(node.getTagName())
@@ -881,19 +882,18 @@
 
 	private void handleNoFormatTag(int start, int end, boolean isOpeningTag) {
 		if (isOpeningTag) {
-			if (this.noFormatTagOpenStart < 0)
-				this.noFormatTagOpenStart = start;
-		} else if (this.noFormatTagOpenStart >= 0) {
-			int openingTagIndex = tokenStartingAt(this.noFormatTagOpenStart);
+			if (this.noFormatOpenTagStartIndex < 0)
+				this.noFormatOpenTagStartIndex = tokenStartingAt(start);
+		} else if (this.noFormatOpenTagStartIndex >= 0) {
 			int closingTagIndex = tokenEndingAt(end);
-			if (openingTagIndex < closingTagIndex) {
-				disableFormatting(openingTagIndex, closingTagIndex, true);
+			if (this.noFormatOpenTagStartIndex < closingTagIndex) {
+				disableFormatting(this.noFormatOpenTagStartIndex, closingTagIndex, true);
 			}
-			this.noFormatTagOpenStart = -1;
+			this.noFormatOpenTagStartIndex = -1;
 		}
 	}
 
-	private void handleFormatCodeTag(int startPos, int endPos, boolean isOpeningTag) {
+	private void handleFormatCodeTag(TagElement tagElement, int startPos, int endPos, boolean isOpeningTag) {
 		if (!this.options.comment_format_source) {
 			handleNoFormatTag(startPos, endPos, isOpeningTag);
 			return;
@@ -901,20 +901,70 @@
 
 		// add empty lines before opening and after closing token
 		handleSeparateLineTag(startPos, endPos);
+		int startIndex = tokenStartingAt(startPos);
+		int endTagIndex = tokenEndingAt(endPos);
 		if (isOpeningTag) {
-			int startIndex = tokenStartingAt(startPos);
 			if (startIndex > 1)
 				this.ctm.get(startIndex).putLineBreaksBefore(2);
 
-			if (this.formatCodeTagOpenEnd < 0)
-				this.formatCodeTagOpenEnd = endPos;
-		} else if (this.formatCodeTagOpenEnd >= 0) {
-			int endTagIndex = tokenEndingAt(endPos);
+			if (this.formatCodeOpenTagEndIndex < 0)
+				this.formatCodeOpenTagEndIndex = endTagIndex;
+		} else if (this.formatCodeOpenTagEndIndex >= 0) {
 			if (endTagIndex < this.ctm.size() - 2)
 				this.ctm.get(endTagIndex).putLineBreaksAfter(2);
 
-			formatCode(startPos, endPos);
-			this.formatCodeTagOpenEnd = -1;
+			List<ASTNode> tags = new ArrayList<ASTNode>(tagElement.fragments());
+			tags.removeIf(f -> !(f instanceof TagElement) || !((TagElement) f).isNested());
+			tags.removeIf(f -> f.getStartPosition() > endPos || f.getStartPosition()
+					+ f.getLength() < this.ctm.get(this.formatCodeOpenTagEndIndex).originalStart);
+			if (!tags.isEmpty()) {
+				disableFormatting(this.formatCodeOpenTagEndIndex, startIndex, true);
+
+				String AT_CODE = TagElement.TAG_CODE;
+				String src = this.ctm.getSource();
+				tags.removeIf(f -> !((TagElement) f).getTagName().equals(AT_CODE));
+				for (ASTNode tagNode : tags) {
+					TagElement tag = (TagElement) tagNode;
+					if (tag.getTagName().equals(AT_CODE)) {
+						int nameEndPos = src.indexOf(AT_CODE, tag.getStartPosition()) + AT_CODE.length() - 1;
+						// int closingBracePos = src.lastIndexOf('}', tag.getStartPosition() + tag.getLength());
+						// TODO bug 570137 workaround
+						int closingBracePos = tag.getStartPosition() + 1;
+						for (int braces = 1; braces > 0 && closingBracePos < src.length(); closingBracePos++) {
+							if (src.charAt(closingBracePos) == '{')
+								braces++;
+							if (src.charAt(closingBracePos) == '}')
+								braces--;
+						}
+						closingBracePos--;
+
+						if (formatCode(tokenEndingAt(nameEndPos), tokenStartingAt(closingBracePos))) {
+							int closingIndex = tokenStartingAt(closingBracePos);
+							Token t = this.ctm.get(closingIndex);
+							this.commentStructure.set(closingIndex,
+									new Token(t, t.originalStart, t.originalEnd, TokenNameCOMMENT_JAVADOC));
+							boolean allowAnnotationAtLineStart = CompilerOptions.versionToJdkLevel(
+									this.sourceLevel) > CompilerOptions.versionToJdkLevel(CompilerOptions.VERSION_14);
+							for (int i = tokenEndingAt(nameEndPos) + 1; i < closingIndex; i++) {
+								t = this.ctm.get(i);
+								if (this.ctm.charAt(t.originalStart) == '@') {
+									if (allowAnnotationAtLineStart) {
+										t.setToEscape(false);
+									} else {
+										t.clearLineBreaksBefore();
+										t.spaceBefore();
+										this.ctm.get(i - 1).clearLineBreaksAfter();
+									}
+								}
+							}
+						}
+					}
+				}
+			} else if (this.formatCodeOpenTagEndIndex >= startIndex - 1
+					|| !formatCode(this.formatCodeOpenTagEndIndex, startIndex)) {
+				disableFormattingExclusively(this.formatCodeOpenTagEndIndex, startIndex);
+			}
+			this.formatCodeOpenTagEndIndex = -1;
 			this.lastFormatCodeClosingTagIndex = this.ctm.findIndex(startPos, -1, true);
 		}
 	}
@@ -1163,12 +1213,9 @@
 		}
 	}
 
-	private void formatCode(int javadocNoFormatCloseStart, int javadocNoFormatCloseEnd) {
-		int openingTagLastIndex = tokenEndingAt(this.formatCodeTagOpenEnd);
-		int closingTagFirstIndex = tokenStartingAt(javadocNoFormatCloseStart);
-
-		int codeStartPosition = this.formatCodeTagOpenEnd + 1;
-		int codeEndPosition = javadocNoFormatCloseStart - 1;
+	private boolean formatCode(int openingIndex, int closingIndex) {
+		int codeStartPosition = this.ctm.get(openingIndex).originalEnd + 1;
+		int codeEndPosition = this.ctm.get(closingIndex).originalStart - 1;
 		StringBuilder codeBuilder = new StringBuilder(codeEndPosition - codeStartPosition + 1);
 		int[] positionMapping = new int[codeEndPosition - codeStartPosition + 1];
 		// ^ index: original source position (minus startPosition), value: position in code string
@@ -1177,16 +1224,15 @@
 		List<Token> formattedTokens = getCommentCodeFormatter().prepareFormattedCode(codeBuilder.toString());
 
 		if (formattedTokens == null) {
-			disableFormattingExclusively(openingTagLastIndex, closingTagFirstIndex);
-			return;
+			return false;
 		}
 
 		formattedTokens = translateFormattedTokens(codeStartPosition, formattedTokens, positionMapping, null);
 
-		Token openingToken = this.ctm.get(openingTagLastIndex);
+		Token openingToken = this.ctm.get(openingIndex);
 		for (Token token : formattedTokens)
 			token.setAlign(token.getAlign() + openingToken.getAlign() + openingToken.getIndent());
-		fixJavadocTagAlign(openingToken, closingTagFirstIndex);
+		fixJavadocTagAlign(openingToken, closingIndex);
 
 		// there are too few linebreaks at the start and end
 		Token start = formattedTokens.get(0);
@@ -1194,11 +1240,12 @@
 		Token end = formattedTokens.get(formattedTokens.size() - 1);
 		end.putLineBreaksAfter(end.getLineBreaksAfter() + 1);
 		// and there may be too many line breaks before closing tag
-		this.ctm.get(closingTagFirstIndex).clearLineBreaksBefore();
+		this.ctm.get(closingIndex).clearLineBreaksBefore();
 
-		List<Token> tokensToReplace = this.commentStructure.subList(openingTagLastIndex + 1, closingTagFirstIndex);
+		List<Token> tokensToReplace = this.commentStructure.subList(openingIndex + 1, closingIndex);
 		tokensToReplace.clear();
 		tokensToReplace.addAll(formattedTokens);
+		return true;
 	}
 
 	private DefaultCodeFormatter getCommentCodeFormatter() {
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java
index fe01346..33d1ac3 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2021 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -7,6 +7,8 @@
  * https://www.eclipse.org/legal/epl-2.0/
  *
  * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Fraunhofer FIRST - extended API and implementation
  *     Technical University Berlin - extended API and implementation
@@ -345,7 +347,7 @@
 	}
 
 	private ASTParser createParser(int kind) {
-		ASTParser parser = ASTParser.newParser(AST.JLS17);
+		ASTParser parser = ASTParser.newParser(AST.JLS18);
 
 		if (kind == K_MODULE_INFO) {
 			parser.setSource(createDummyModuleInfoCompilationUnit());
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/TokenManager.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/TokenManager.java
index 33872da..28d0633 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/TokenManager.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/TokenManager.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2014, 2021 Mateusz Matela and others.
+ * Copyright (c) 2014, 2022 Mateusz Matela and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -14,6 +14,7 @@
 package org.eclipse.jdt.internal.formatter;
 
 import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameCOMMENT_LINE;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameCOMMENT_JAVADOC;
 import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameNotAToken;
 import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameStringLiteral;
 import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameTextBlock;
@@ -303,7 +304,7 @@
 	private String getEscapedTokenString(Token token) {
 		if (token.getLineBreaksBefore() > 0 && charAt(token.originalStart) == '@') {
 			return "&#64;" + this.source.substring(token.originalStart + 1, token.originalEnd + 1); //$NON-NLS-1$
-		} else if (token.tokenType == TokenNameNotAToken) {
+		} else if (token.tokenType == TokenNameNotAToken || token.tokenType == TokenNameCOMMENT_JAVADOC) {
 			String text = token.toString(this.source);
 			Matcher matcher = COMMENT_LINE_ANNOTATION_PATTERN.matcher(text);
 			if (matcher.find()) {
diff --git a/org.eclipse.jdt.core/grammar/java.g b/org.eclipse.jdt.core/grammar/java.g
index f66b9e7..1b4f08e 100644
--- a/org.eclipse.jdt.core/grammar/java.g
+++ b/org.eclipse.jdt.core/grammar/java.g
@@ -2145,6 +2145,11 @@
 /:$readableName Resource:/
 /:$compliance 1.9:/
 
+Resource ::= 'this'
+/.$putCase consumeResourceAsThis(); $break ./
+/:$readableName Resource:/
+/:$compliance 1.9:/
+
 Resource ::= FieldAccess
 /.$putCase consumeResourceAsFieldAccess(); $break ./
 /:$readableName Resource:/
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionRequestor.java
index 60b8a5d..edcc90f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionRequestor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2019 IBM Corporation and others.
+ * Copyright (c) 2004, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -151,6 +151,19 @@
 	}
 
 	/**
+	 * Returns whether the given type proposal is ignored.
+	 *
+	 * @param fullTypeName the proposed type name of CompletionProposal
+	 * @return <code>true</code> if the given type name is ignored by
+	 * this requestor, and <code>false</code> if it is of interest
+	 *
+	 * @since 3.30
+	 */
+	public boolean isIgnored(char[] fullTypeName) {
+		return false;
+	}
+
+	/**
 	 * Returns whether a proposal of a given kind with a required proposal
 	 * of the given kind is allowed.
 	 *
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 3350fd4..38d653d 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
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2021 IBM Corporation and others.
+ * Copyright (c) 2000, 2022 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -3174,12 +3174,18 @@
 	public static final String VERSION_17 = "17"; //$NON-NLS-1$
 	/**
 	 * Configurable option value: {@value}.
+	 * @since 3.30
+	 * @category OptionValue
+	 */
+	public static final String VERSION_18 = "18"; //$NON-NLS-1$
+	/**
+	 * Configurable option value: {@value}.
 	 * @since 3.4
 	 * @category OptionValue
 	 */
 	public static final String VERSION_CLDC_1_1 = "cldc1.1"; //$NON-NLS-1$
 	private static List<String> allVersions = Collections.unmodifiableList(Arrays.asList(VERSION_CLDC_1_1, VERSION_1_1, VERSION_1_2, VERSION_1_3, VERSION_1_4, VERSION_1_5,
-			VERSION_1_6, VERSION_1_7, VERSION_1_8, VERSION_9, VERSION_10, VERSION_11, VERSION_12, VERSION_13, VERSION_14, VERSION_15, VERSION_16, VERSION_17));
+			VERSION_1_6, VERSION_1_7, VERSION_1_8, VERSION_9, VERSION_10, VERSION_11, VERSION_12, VERSION_13, VERSION_14, VERSION_15, VERSION_16, VERSION_17, VERSION_18));
 
 	/**
 	 * Returns all {@link JavaCore}{@code #VERSION_*} levels in the order of their
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
index c10d6ce..d02d153 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
@@ -2645,12 +2645,6 @@
 						elementRemoved(element, delta, rootInfo);
 					}
 					this.state.addClasspathValidation(rootInfo.project);
-				} else if ((flags & IResourceDelta.CONTENT) != 0 || (flags & IResourceDelta.ENCODING) != 0) {
-					// content or encoding has changed
-					element = createElement(delta.getResource(), elementType, rootInfo);
-					if (element == null) return false;
-					updateIndex(element, delta);
-					contentChanged(element);
 				} else if (elementType == IJavaElement.JAVA_PROJECT) {
 					if ((flags & IResourceDelta.OPEN) != 0) {
 						// project has been opened or closed
@@ -2708,6 +2702,19 @@
 							return false; // when a project's nature is added/removed don't process children
 						}
 					}
+					if ((flags & IResourceDelta.CONTENT) != 0 || (flags & IResourceDelta.ENCODING) != 0) {
+						// content or encoding has changed
+						element = createElement(delta.getResource(), elementType, rootInfo);
+						if (element == null) return false;
+						updateIndex(element, delta);
+						contentChanged(element);
+					}
+				} else if ((flags & IResourceDelta.CONTENT) != 0 || (flags & IResourceDelta.ENCODING) != 0) {
+					// content or encoding has changed
+					element = createElement(delta.getResource(), elementType, rootInfo);
+					if (element == null) return false;
+					updateIndex(element, delta);
+					contentChanged(element);
 				}
 				return true;
 		}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java
index 85cadc7..649f978 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java
@@ -786,6 +786,7 @@
 	LinkedHashSet cycleParticipants = new LinkedHashSet(3);
 	this.javaProject.updateCycleParticipants(new ArrayList(), cycleParticipants, new HashMap<>(), this.workspaceRoot, new HashSet(3), null);
 	IPath currentPath = this.javaProject.getPath();
+	Set<IProject> toRebuild = new HashSet<>();
 	Iterator i= cycleParticipants.iterator();
 	while (i.hasNext()) {
 		IPath participantPath = (IPath) i.next();
@@ -795,11 +796,13 @@
 				if (DEBUG)
 					System.out.println("JavaBuilder: Requesting another build iteration since cycle participant " + project.getName() //$NON-NLS-1$
 						+ " has not yet seen some structural changes"); //$NON-NLS-1$
-				needRebuild();
-				return;
+				toRebuild.add(project);
 			}
 		}
 	}
+	if (!toRebuild.isEmpty()) {
+		requestProjectsRebuild(toRebuild);
+	}
 }
 
 private void printLocations(ClasspathLocation[] newLocations, ClasspathLocation[] oldLocations) {
diff --git a/org.eclipse.jdt.core/pom.xml b/org.eclipse.jdt.core/pom.xml
index 33e83fb..b4ba476 100644
--- a/org.eclipse.jdt.core/pom.xml
+++ b/org.eclipse.jdt.core/pom.xml
@@ -14,10 +14,10 @@
   <parent>
     <artifactId>eclipse.jdt.core</artifactId>
     <groupId>org.eclipse.jdt</groupId>
-    <version>4.23.0-SNAPSHOT</version>
+    <version>4.24.0-SNAPSHOT</version>
   </parent>
   <artifactId>org.eclipse.jdt.core</artifactId>
-  <version>3.29.0-SNAPSHOT</version>
+  <version>3.30.0-SNAPSHOT</version>
   <packaging>eclipse-plugin</packaging>
 
   <properties>
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddJarFileToIndex.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddJarFileToIndex.java
index 496ef0c..2250f10 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddJarFileToIndex.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddJarFileToIndex.java
@@ -17,6 +17,7 @@
 import java.io.IOException;
 import java.net.URI;
 import java.nio.charset.Charset;
+import java.nio.file.NoSuchFileException;
 import java.util.Enumeration;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipError;
@@ -26,7 +27,10 @@
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.search.IJavaSearchScope;
 import org.eclipse.jdt.core.search.SearchEngine;
@@ -279,7 +283,12 @@
 				monitor.exitWrite(); // free write lock
 			}
 		} catch (IOException | ZipError e) {
-			org.eclipse.jdt.internal.core.util.Util.log(e, "Failed to index " + this.containerPath); //$NON-NLS-1$
+			if (e instanceof NoSuchFileException) {
+				IStatus info = new Status(IStatus.INFO, JavaCore.PLUGIN_ID, "File no longer exists: " + this.containerPath, e); //$NON-NLS-1$
+				org.eclipse.jdt.internal.core.util.Util.log(info);
+			} else {
+				org.eclipse.jdt.internal.core.util.Util.log(e, "Failed to index " + this.containerPath); //$NON-NLS-1$
+			}
 			this.manager.removeIndex(this.containerPath);
 			return false;
 		}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java
index 0921dda..9e7a8f2 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java
@@ -784,7 +784,7 @@
  */
 public void indexSourceFolder(JavaProject javaProject, IPath sourceFolder, char[][] inclusionPatterns, char[][] exclusionPatterns) {
 	IProject project = javaProject.getProject();
-	if (this.awaitingJobs.size() > 1) {
+	if (awaitingJobsCount() > 1) {
 		// skip it if a job to index the project is already in the queue
 		IndexRequest request = new IndexAllProject(project, this);
 		if (isJobWaiting(request)) return;
@@ -1059,7 +1059,7 @@
  */
 public void removeSourceFolderFromIndex(JavaProject javaProject, IPath sourceFolder, char[][] inclusionPatterns, char[][] exclusionPatterns) {
 	IProject project = javaProject.getProject();
-	if (this.awaitingJobs.size() > 1) {
+	if (awaitingJobsCount() > 1) {
 		// skip it if a job to index the project is already in the queue
 		IndexRequest request = new IndexAllProject(project, this);
 		if (isJobWaiting(request)) return;
@@ -1150,9 +1150,10 @@
 	}
 	synchronized (this) {
 		IPath containerPath = new Path(index.containerPath);
-		if (this.awaitingJobs.size() > 1) {
+		int awaitingJobsCount = awaitingJobsCount();
+		if (awaitingJobsCount > 1) {
 			// Start at the end and go backwards
-			ListIterator<IJob> iterator = this.awaitingJobs.listIterator(this.awaitingJobs.size());
+			ListIterator<IJob> iterator = this.awaitingJobs.listIterator(awaitingJobsCount);
 			IJob first = this.awaitingJobs.get(0);
 			while (iterator.hasPrevious()) {
 				IJob job = iterator.previous();
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocatorParser.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocatorParser.java
index 0a6b99f..986589e 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocatorParser.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocatorParser.java
@@ -471,8 +471,17 @@
 
 private void matchPatternVariable() {
 	if (this.patternFineGrain == 0) {
-		InstanceOfExpression expression = (InstanceOfExpression) this.expressionStack[this.expressionPtr];
-		LocalDeclaration elementVariable = expression.elementVariable;
+		Expression expr = this.expressionStack[this.expressionPtr];
+		LocalDeclaration elementVariable = null;
+		if (expr instanceof InstanceOfExpression) {
+			InstanceOfExpression expression = (InstanceOfExpression) this.expressionStack[this.expressionPtr];
+			elementVariable = expression.elementVariable;
+		} else if (expr instanceof AND_AND_Expression) {
+			// Refer to Parser#consumeInstanceOfExpression() to understand how
+			// we can ever expect AND_AND_Expression in place of InstanceOfExpression
+			InstanceOfExpression expression = (InstanceOfExpression) ((AND_AND_Expression) expr).left;
+			elementVariable = expression.elementVariable;
+		}
 		if (elementVariable != null) {
 			// if pattern variable present, match that
 			this.patternLocator.match(elementVariable, this.nodeSet);
diff --git a/plugins/org.eclipse.objectteams.otdt/META-INF/MANIFEST.MF b/plugins/org.eclipse.objectteams.otdt/META-INF/MANIFEST.MF
index 660b091..5a9102f 100644
--- a/plugins/org.eclipse.objectteams.otdt/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.objectteams.otdt/META-INF/MANIFEST.MF
@@ -13,7 +13,7 @@
  org.eclipse.objectteams.otdt.internal.core.ext;x-internal:=true
 Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.8.0,4.0.0)",
  org.eclipse.core.resources;bundle-version="[3.8.0,4.0.0)",
- org.eclipse.jdt.core;bundle-version="[3.29.0.OTDT_r282,4.0.0)",
+ org.eclipse.jdt.core;bundle-version="[3.30.0.OTDT_r282,4.0.0)",
  org.eclipse.jdt.launching;bundle-version="[3.6.100,4.0.0)",
  org.eclipse.debug.core;bundle-version="[3.7.100,4.0.0)",
  org.eclipse.osgi;bundle-version="[3.10.0,4.0.0)",
diff --git a/releng/map/otdt.map.in b/releng/map/otdt.map.in
index f5352a7..4c93c7f 100644
--- a/releng/map/otdt.map.in
+++ b/releng/map/otdt.map.in
@@ -9,7 +9,7 @@
 feature@org.eclipse.objectteams.otequinox.turbo=GIT,repo=https://git.eclipse.org/r/objectteams/org.eclipse.objectteams.git,path=features/org.eclipse.objectteams.otequinox.turbo.feature,tag=builds/201506091717

 

 !-- Also don't use version numbers for those plugins that hold the various otre jars: --

-plugin@org.eclipse.jdt.core,3.29.0.OTDT_r282_qualifier=GIT,repo=https://git.eclipse.org/r/objectteams/org.eclipse.objectteams.git,path=org.eclipse.jdt.core

+plugin@org.eclipse.jdt.core,3.30.0.OTDT_r282_qualifier=GIT,repo=https://git.eclipse.org/r/objectteams/org.eclipse.objectteams.git,path=org.eclipse.jdt.core

 

 !next plug-in don't specify version so that org.eclipse.objectteams.runtime/customBuildCallbacks.xml will find the plug-in directory:

 plugin@org.eclipse.objectteams.otdt=GIT,repo=https://git.eclipse.org/r/objectteams/org.eclipse.objectteams.git,path=plugins/org.eclipse.objectteams.otdt