Bug 533619 - [11][batch][compiler] support command line --enable-preview

Change-Id: I7e37f168e8011ca88d68a302ffb9e4a78526997b
Signed-off-by: Jay Arthanareeswaran <jarthana@in.ibm.com>
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
index bdaf044..f24a3b8 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
@@ -1017,6 +1017,7 @@
 			"		<option key=\"org.eclipse.jdt.core.compiler.generateClassFiles\" value=\"enabled\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.maxProblemPerUnit\" value=\"100\"/>\n" +
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.APILeak\" value=\"warning\"/>\n" + 
+			"		<option key=\"org.eclipse.jdt.core.compiler.problem.EnablePreviews\" value=\"disabled\"/>\n" +
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.annotationSuperInterface\" value=\"warning\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.assertIdentifier\" value=\"warning\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.autoboxing\" value=\"ignore\"/>\n" + 
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest2.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest2.java
new file mode 100644
index 0000000..ff8095f
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest2.java
@@ -0,0 +1,111 @@
+package org.eclipse.jdt.core.tests.compiler.regression;
+
+import java.io.File;
+
+import junit.framework.Test;
+
+@SuppressWarnings({ "rawtypes" })
+public class BatchCompilerTest2 extends AbstractBatchCompilerTest {
+
+	static {
+//		TESTS_NAMES = new String[] { "test440477" };
+//		TESTS_NUMBERS = new int[] { 306 };
+//		TESTS_RANGE = new int[] { 298, -1 };
+	}
+	
+	/**
+	 * This test suite only needs to be run on one compliance.
+	 * As it includes some specific 1.5 tests, it must be used with a least a 1.5 VM
+	 * and not be duplicated in general test suite.
+	 * @see TestAll
+	 */
+	public static Test suite() {
+		return buildMinimalComplianceTestSuite(testClass(), F_11);
+	}
+	public static Class testClass() {
+		return BatchCompilerTest2.class;
+	}
+	public BatchCompilerTest2(String name) {
+		super(name);
+	}
+	public void test001() {
+		this.runNegativeTest(
+				new String[] {
+					"X.java",
+					"import java.util.List;\n" +
+					"\n" +
+					"@SuppressWarnings(\"all\"//$NON-NLS-1$\n" +
+					")\n" +
+					"public class X {\n" +
+					"	public static void main(String[] args) {\n" +
+					"		if (false) {\n" +
+					"			;\n" +
+					"		} else {\n" +
+					"		}\n" +
+					"		Zork z;\n" +
+					"	}\n" +
+					"}"
+		        },
+		        "\"" + OUTPUT_DIR +  File.separator + "X.java\""
+		        + " -10 --enable-preview",
+		        "",
+		        "Preview of features is supported only at the latest source level\n",
+		        true);
+}
+	public void test002() {
+		this.runNegativeTest(
+				new String[] {
+					"X.java",
+					"import java.util.List;\n" +
+					"\n" +
+					"@SuppressWarnings(\"all\"//$NON-NLS-1$\n" +
+					")\n" +
+					"public class X {\n" +
+					"	public static void main(String[] args) {\n" +
+					"		if (false) {\n" +
+					"			;\n" +
+					"		} else {\n" +
+					"		}\n" +
+					"		Zork z;\n" +
+					"	}\n" +
+					"}"
+		        },
+		        "\"" + OUTPUT_DIR +  File.separator + "X.java\""
+		        + " -11 --enable-preview",
+		        "",
+		        "----------\n" + 
+        		"1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/X.java (at line 11)\n" + 
+        		"	Zork z;\n" + 
+        		"	^^^^\n" + 
+        		"Zork cannot be resolved to a type\n" + 
+        		"----------\n" + 
+        		"1 problem (1 error)\n",
+		        true);
+}
+public void test003() {
+	this.runNegativeTest(
+			new String[] {
+					"X.java",
+					"public class X {\n" +
+					"    public static void main(String [] args) {\n" +
+					"        I lam = (Integer  x, var y) -> {System.out.println(\"SUCCESS \" + x);};\n" +
+					"        lam.apply(20, 200);\n" +
+					"    }\n" +
+					"}\n" +
+					"interface I {\n" +
+					"    public void apply(Integer k, Integer z);\n" +
+					"}\n"
+			},
+			"\"" + OUTPUT_DIR +  File.separator + "X.java\""
+					+ " -11 --enable-preview",
+					"",
+					"----------\n" + 
+					"1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/X.java (at line 3)\n" + 
+					"	I lam = (Integer  x, var y) -> {System.out.println(\"SUCCESS \" + x);};\n" + 
+					"	                         ^\n" + 
+					"\'var\' cannot be mixed with non-var parameters\n" + 
+					"----------\n" + 
+					"1 problem (1 error)\n",
+					true);
+}
+}
\ No newline at end of file
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 d538f71..8b4d183 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
@@ -115,12 +115,15 @@
 			}
 		}
 	}
+	// Add one for "preview", which doesn't have any irritant at the moment
+	matcher.put("preview", "preview");
 	String [] allTokens = CompilerOptions.warningTokens;
 	int length = allTokens.length;
 	matcher.put("all", "all"); // all gets undetected in the From/To loop
 	assertEquals(allTokens.length, matcher.size());
 	for (int i = 0; i < length; i++) {
-		assertNotNull(matcher.get(allTokens[i]));
+		Object object = matcher.get(allTokens[i]);
+		assertNotNull(object);
 	}
 }
 
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 cbe0a0c..85329f3 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
@@ -1385,6 +1385,7 @@
 	// == Main.NONE: absorbent element, do not output class files;
 	// else: use as the path of the directory into which class files must
 	//       be written.
+	protected boolean enablePreview;
 	protected String releaseVersion;
 	private boolean didSpecifySource;
 	private boolean didSpecifyTarget;
@@ -2207,6 +2208,11 @@
 					mode = INSIDE_BOOTCLASSPATH_start;
 					continue;
 				}
+				if (currentArg.equals("--enable-preview")) { //$NON-NLS-1$
+					this.enablePreview = true;
+					mode = DEFAULT;
+					continue;
+				}
 				if (currentArg.equals("--system")) { //$NON-NLS-1$
 					mode = INSIDE_SYSTEM;
 					continue;
@@ -3071,6 +3077,11 @@
 		mode = DEFAULT;
 		continue;
 	}
+	if (this.enablePreview) {
+		this.options.put(
+				CompilerOptions.OPTION_EnablePreviews,
+				CompilerOptions.ENABLED);
+	}
 
 	// set DocCommentSupport, with appropriate side effects on defaults if
 	// javadoc is not enabled
@@ -5479,7 +5490,10 @@
 		long ver = CompilerOptions.versionToJdkLevel(sourceVersion);
 		if(this.complianceLevel < ver)
 			throw new IllegalArgumentException(this.bind("configure.incompatibleComplianceForSource", this.options.get(CompilerOptions.OPTION_Compliance), sourceVersion)); //$NON-NLS-1$
-	} 	
+	}
+	if (this.enablePreview && this.complianceLevel != ClassFileConstants.getLatestJDKLevel()) {
+		throw new IllegalArgumentException(this.bind("configure.unsupportedPreview")); //$NON-NLS-1$
+	}
 
 	// check and set compliance/source/target compatibilities
 	if (this.didSpecifyTarget) {
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 7923d00..a6a6ed7 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
@@ -88,6 +88,7 @@
 configure.repetition = repetition must be a positive integer: {0}
 configure.maxProblems = max problems must be a positive integer: {0}
 configure.invalidNowarnOption = invalid syntax for nowarn option: {0}
+configure.unsupportedPreview = Preview of features is supported only at the latest source level
 
 configure.invalidErrorConfiguration = invalid error configuration: ''{0}''
 configure.invalidError = invalid error token: ''{0}''. Ignoring this error token and compiling
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 3cfa30a..4c21bc5 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
@@ -203,6 +203,8 @@
 	public static final String OPTION_ReportAPILeak = "org.eclipse.jdt.core.compiler.problem.APILeak"; //$NON-NLS-1$
 	public static final String OPTION_ReportUnstableAutoModuleName = "org.eclipse.jdt.core.compiler.problem.unstableAutoModuleName";   //$NON-NLS-1$
 
+	public static final String OPTION_EnablePreviews = "org.eclipse.jdt.core.compiler.problem.EnablePreviews"; //$NON-NLS-1$
+
 	/**
 	 * Possible values for configurable options
 	 */
@@ -332,6 +334,8 @@
 	public static final int UsingTerminallyDeprecatedAPI = IrritantSet.GROUP2 | ASTNode.Bit24;
 	public static final int APILeak = IrritantSet.GROUP2 | ASTNode.Bit25;
 	public static final int UnstableAutoModuleName = IrritantSet.GROUP2 | ASTNode.Bit26;
+	// Dummy feature, but
+	//public static final int DummyPreviewFeatureWarning = IrritantSet.GROUP2 | ASTNode.Bit27;
 
 
 	// Severity level for handlers
@@ -517,6 +521,9 @@
 	/** Not directly configurable, derived from other options by LookupEnvironment.usesNullTypeAnnotations() */
 	public Boolean useNullTypeAnnotations = null;
 
+	/** Master flag to enabled/disable all preview features */
+	public boolean enablePreviewFeatures;
+
 	// keep in sync with warningTokenToIrritant and warningTokenFromIrritant
 	public final static String[] warningTokens = {
 		"all", //$NON-NLS-1$
@@ -547,6 +554,7 @@
 		"unlikely-arg-type", //$NON-NLS-1$
 		"unqualified-field-access", //$NON-NLS-1$
 		"unused", //$NON-NLS-1$
+		"preview", //$NON-NLS-1$
 	};
 
 	/**
@@ -1086,6 +1094,8 @@
 				return "exports"; //$NON-NLS-1$
 			case UnstableAutoModuleName:
 				return "module"; //$NON-NLS-1$
+			//case DummyPreviewFeatureWarning:
+			//	return "preview"; //$NON-NLS-1$
 		}
 		return null;
 	}
@@ -1144,6 +1154,11 @@
 				if ("null".equals(warningToken)) //$NON-NLS-1$
 					return IrritantSet.NULL;
 				break;
+			case 'p' :
+				if ("preview".equals(warningToken)) { //$NON-NLS-1$
+					return IrritantSet.PREVIEW;
+				}
+				break;
 			case 'r' :
 				if ("rawtypes".equals(warningToken)) //$NON-NLS-1$
 					return IrritantSet.RAW;
@@ -1330,6 +1345,7 @@
 		optionsMap.put(OPTION_ReportUnlikelyEqualsArgumentType, getSeverityString(UnlikelyEqualsArgumentType));
 		optionsMap.put(OPTION_ReportAPILeak, getSeverityString(APILeak));
 		optionsMap.put(OPTION_ReportUnstableAutoModuleName, getSeverityString(UnstableAutoModuleName));
+		optionsMap.put(OPTION_EnablePreviews, this.enablePreviewFeatures ? ENABLED : DISABLED);
 		return optionsMap;
 	}
 
@@ -1528,6 +1544,7 @@
 		this.reportMissingEnumCaseDespiteDefault = false;
 
 		this.complainOnUninternedIdentityComparison = false;
+		this.enablePreviewFeatures = false;
 	}
 
 	public void set(Map<String, String> optionsMap) {
@@ -2036,6 +2053,13 @@
 				this.complainOnUninternedIdentityComparison = false;
 			}
 		}
+		if ((optionValue = optionsMap.get(OPTION_EnablePreviews)) != null) {
+			if (ENABLED.equals(optionValue)) {
+				this.enablePreviewFeatures = true;
+			} else if (DISABLED.equals(optionValue)) {
+				this.enablePreviewFeatures = false;
+			}
+		}
 	}
 
 	private String[] stringToNameList(String optionValue) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java
index e77b9be..c7a53dd 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java
@@ -74,6 +74,7 @@
 	public static final IrritantSet MODULE = new IrritantSet(CompilerOptions.UnstableAutoModuleName);
 
 	public static final IrritantSet JAVADOC = new IrritantSet(CompilerOptions.InvalidJavadoc);
+	public static final IrritantSet PREVIEW = new IrritantSet(0);
 	public static final IrritantSet COMPILER_DEFAULT_ERRORS = new IrritantSet(0); // no optional error by default	
 	public static final IrritantSet COMPILER_DEFAULT_WARNINGS = new IrritantSet(0); // see static initializer below
 	public static final IrritantSet COMPILER_DEFAULT_INFOS = new IrritantSet(0); // As of now, no default values
@@ -186,9 +187,10 @@
 
 		UNLIKELY_ARGUMENT_TYPE
 			.set(CompilerOptions.UnlikelyEqualsArgumentType);
+		//PREVIEW.set(CompilerOptions.DummyPreviewFeatureWarning);
 	}
-
 	// Internal state
+
 	private int[] bits = new int[GROUP_MAX];
 
 	/**