Bug 564828 - [14] Content assist for public rec should give record 

Change-Id: I60317dea718e183a12f86ed83bc098b98009dc9f
Signed-off-by: Vikas Chandra <Vikas.Chandra@in.ibm.com>
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests14.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests14.java
index b0abee2..c251d3a 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests14.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests14.java
@@ -341,4 +341,50 @@
 		this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
 		assertResults("", requestor.getResults());
 	}
+	public void testBug564828_1() throws JavaModelException {
+		this.workingCopies = new ICompilationUnit[1];
+		this.workingCopies[0] = getWorkingCopy(
+				"/Completion/src/Point.java",
+				"public reco {\n" +
+				"}");
+		this.workingCopies[0].getJavaProject(); //assuming single project for all working copies
+		CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true);
+		requestor.allowAllRequiredProposals();
+		String str = this.workingCopies[0].getSource();
+		String completeBehind = "reco";
+		int cursorLocation = str.indexOf(completeBehind) + completeBehind.length();
+		this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
+		assertResults(
+				"record[RESTRICTED_IDENTIFIER]{record, null, null, record, null, 49}",
+				requestor.getResults());
+
+	}
+
+	//check if local variable record shows up
+	public void testBug564828_2() throws JavaModelException {
+		this.workingCopies = new ICompilationUnit[1];
+		this.workingCopies[0] = getWorkingCopy(
+				"/Completion/src/Point.java",
+				"public class Point {\n" +
+				"private void method(){\n" +
+				"int record;\n" +
+				"{\n" +
+				" /*here*/rec\n" +
+				"}\n" +
+				"}\n" +
+
+				"}");
+		this.workingCopies[0].getJavaProject(); //assuming single project for all working copies
+		CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true);
+		requestor.allowAllRequiredProposals();
+		String str = this.workingCopies[0].getSource();
+		String completeBehind = "/*here*/rec";
+		int cursorLocation = str.indexOf(completeBehind) + completeBehind.length();
+		this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
+		assertResults(
+				"Record[TYPE_REF]{Record, java.lang, Ljava.lang.Record;, null, null, 42}\n"+
+				"record[LOCAL_VARIABLE_REF]{record, null, I, record, null, 52}",
+				requestor.getResults());
+
+	}
 }
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 6eb59df..cb26327 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
@@ -23,8 +23,10 @@
 import org.eclipse.jdt.core.Flags;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.Signature;
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.internal.codeassist.InternalCompletionContext;
+import org.eclipse.jdt.internal.codeassist.impl.RestrictedIdentifiers;
 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.util.ObjectVector;
 import org.eclipse.jdt.internal.core.JavaElement;
@@ -345,8 +347,12 @@
 			case CompletionProposal.FIELD_REF_WITH_CASTED_RECEIVER :
 				buffer.append("FIELD_REF_WITH_CASTED_RECEIVER"); //$NON-NLS-1$
 				break;
-			case CompletionProposal.KEYWORD :
-				buffer.append("KEYWORD"); //$NON-NLS-1$
+			case CompletionProposal.KEYWORD :{
+				if(CharOperation.equals(proposal.getCompletion(), RestrictedIdentifiers.RECORD))
+						buffer.append("RESTRICTED_IDENTIFIER");
+					else
+						buffer.append("KEYWORD"); //$NON-NLS-1$
+			}
 				break;
 			case CompletionProposal.LABEL_REF :
 				buffer.append("LABEL_REF"); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
index 0d632f0..68aea7e 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2019 IBM Corporation and others.
+ * Copyright (c) 2000, 2020 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -1515,7 +1515,7 @@
 	}
 	return false;
 }
-private boolean checkKeyword() {
+private boolean checkKeywordAndRestrictedIdentifiers() {
 	if (this.currentElement instanceof RecoveredUnit) {
 		RecoveredUnit unit = (RecoveredUnit) this.currentElement;
 		if (unit.unitDeclaration.isModuleInfo()) return false;
@@ -1526,18 +1526,18 @@
 			char[] ident = this.identifierStack[ptr];
 			long pos = this.identifierPositionStack[ptr];
 
-			char[][] keywords = new char[Keywords.COUNT][];
+			char[][] keywordsAndRestrictedIndentifiers = new char[Keywords.COUNT+RestrictedIdentifiers.COUNT][];
 			int count = 0;
 			if(unit.typeCount == 0
 				&& (!this.compilationUnit.isPackageInfo() || this.compilationUnit.currentPackage != null)
 				&& this.lastModifiers == ClassFileConstants.AccDefault) {
-				keywords[count++] = Keywords.IMPORT;
+				keywordsAndRestrictedIndentifiers[count++] = Keywords.IMPORT;
 			}
 			if(unit.typeCount == 0
 				&& unit.importCount == 0
 				&& this.lastModifiers == ClassFileConstants.AccDefault
 				&& this.compilationUnit.currentPackage == null) {
-				keywords[count++] = Keywords.PACKAGE;
+				keywordsAndRestrictedIndentifiers[count++] = Keywords.PACKAGE;
 			}
 			if (!this.compilationUnit.isPackageInfo()) {
 				if((this.lastModifiers & ClassFileConstants.AccPublic) == 0) {
@@ -1548,31 +1548,34 @@
 						}
 					}
 					if(hasNoPublicType) {
-						keywords[count++] = Keywords.PUBLIC;
+						keywordsAndRestrictedIndentifiers[count++] = Keywords.PUBLIC;
 					}
 				}
 				if((this.lastModifiers & ClassFileConstants.AccAbstract) == 0
 					&& (this.lastModifiers & ClassFileConstants.AccFinal) == 0) {
-					keywords[count++] = Keywords.ABSTRACT;
+					keywordsAndRestrictedIndentifiers[count++] = Keywords.ABSTRACT;
 				}
 				if((this.lastModifiers & ClassFileConstants.AccAbstract) == 0
 					&& (this.lastModifiers & ClassFileConstants.AccFinal) == 0) {
-					keywords[count++] = Keywords.FINAL;
+					keywordsAndRestrictedIndentifiers[count++] = Keywords.FINAL;
 				}
 
-				keywords[count++] = Keywords.CLASS;
+				keywordsAndRestrictedIndentifiers[count++] = Keywords.CLASS;
 				if (this.options.complianceLevel >= ClassFileConstants.JDK1_5) {
-					keywords[count++] = Keywords.ENUM;
+					keywordsAndRestrictedIndentifiers[count++] = Keywords.ENUM;
+				}
+				if((this.lastModifiers & ClassFileConstants.AccFinal) == 0) {
+					keywordsAndRestrictedIndentifiers[count++] = Keywords.INTERFACE;
+				}
+				if (this.options.complianceLevel >= ClassFileConstants.JDK14 && this.options.enablePreviewFeatures == true) {
+					keywordsAndRestrictedIndentifiers[count++] = RestrictedIdentifiers.RECORD;
 				}
 
-				if((this.lastModifiers & ClassFileConstants.AccFinal) == 0) {
-					keywords[count++] = Keywords.INTERFACE;
-				}
 			}
 			if(count != 0) {
-				System.arraycopy(keywords, 0, keywords = new char[count][], 0, count);
+				System.arraycopy(keywordsAndRestrictedIndentifiers, 0, keywordsAndRestrictedIndentifiers = new char[count][], 0, count);
 
-				this.assistNode = new CompletionOnKeyword2(ident, pos, keywords);
+				this.assistNode = new CompletionOnKeyword2(ident, pos, keywordsAndRestrictedIndentifiers);
 				this.lastCheckPoint = this.assistNode.sourceEnd + 1;
 				this.isOrphanCompletionNode = true;
 				return true;
@@ -2182,7 +2185,8 @@
 	//if (assistNode != null) return;
 
 	if (checkMemberValueName()) return;
-	if (checkKeyword()) return;
+
+	if(checkKeywordAndRestrictedIdentifiers()) return;
 	if (checkModuleInfoConstructs()) return;
 	if (checkRecoveredType()) return;
 	if (checkRecoveredMethod()) return;
@@ -2712,7 +2716,7 @@
 
 		// recovery
 		if (this.currentElement != null) {
-			if(!checkKeyword() && !(this.currentElement instanceof RecoveredUnit && ((RecoveredUnit)this.currentElement).typeCount == 0)) {
+			if(!checkKeywordAndRestrictedIdentifiers() && !(this.currentElement instanceof RecoveredUnit && ((RecoveredUnit)this.currentElement).typeCount == 0)) {
 				int nameSourceStart = (int)(this.identifierPositionStack[this.identifierPtr] >>> 32);
 				this.intPtr--;
 				TypeReference type = getTypeReference(this.intStack[this.intPtr--]);
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Keywords.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Keywords.java
index cf7836f..99a9f2c 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Keywords.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Keywords.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2019 IBM Corporation and others.
+ * Copyright (c) 2000, 2020 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -70,4 +70,5 @@
 	char[] FALSE = "false".toCharArray(); //$NON-NLS-1$
 	char[] NULL = "null".toCharArray(); //$NON-NLS-1$
 	char[] VAR = "var".toCharArray(); //$NON-NLS-1$ // Admittedly not a full blown keyword, just "reserved"
+
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/RestrictedIdentifiers.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/RestrictedIdentifiers.java
new file mode 100644
index 0000000..6914830
--- /dev/null
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/RestrictedIdentifiers.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2020 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.codeassist.impl;
+
+public interface RestrictedIdentifiers {
+	int COUNT = 1;
+
+    char[] RECORD = "record".toCharArray();//$NON-NLS-1$
+
+}