Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephan Herrmann2021-08-12 11:43:40 +0000
committerStephan Herrmann2021-08-12 14:15:50 +0000
commit43b3339093473b2e9632f287b07b19f344c846fe (patch)
treed0591a7a0c0c754c2e7ee2eaf5b98a0bef7ed6b3
parente16e7d340a485767e3f2c423a687bef97afd2327 (diff)
downloadeclipse.jdt.core-43b3339093473b2e9632f287b07b19f344c846fe.tar.gz
eclipse.jdt.core-43b3339093473b2e9632f287b07b19f344c846fe.tar.xz
eclipse.jdt.core-43b3339093473b2e9632f287b07b19f344c846fe.zip
Bug 574978 - [content assist] keywords are not proposed inside blockI20210813-1800I20210812-1800
with subsequent statement Change-Id: I19d85a5609a6b879c7692af609e727df511aaf29 Reviewed-on: https://git.eclipse.org/r/c/jdt/eclipse.jdt.core/+/183953 Tested-by: JDT Bot <jdt-bot@eclipse.org> Reviewed-by: Stephan Herrmann <stephan.herrmann@berlin.de>
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests3.java1
-rw-r--r--org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java9
-rw-r--r--org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java9
-rw-r--r--org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java228
4 files changed, 135 insertions, 112 deletions
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests3.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests3.java
index 2262a2066e..44b0f49356 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests3.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests3.java
@@ -922,6 +922,7 @@ public void testBug574338_from574215c14() throws CoreException {
int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
assertResults(
+ "for[KEYWORD]{for, null, null, for, null, 49}\n" +
"fooo[LOCAL_VARIABLE_REF]{fooo, null, Ljava.lang.String;, fooo, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_UNQUALIFIED + R_NON_RESTRICTED) + "}",
requestor.getResults());
} finally {
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 920bfebc8a..b8dc2c669b 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
@@ -3907,8 +3907,15 @@ public final class CompletionEngine
if (receiverType != null && receiverType.isValidBinding()) {
findVariablesAndMethods(this.completionToken, scope, FakeInvocationSite, scope, false, false);
}
+ // ... or a keyword (possibly starting a new statement):
+ if (!this.requestor.isIgnored(CompletionProposal.KEYWORD)) {
+ if (this.completionToken != null && this.completionToken.length != 0) {
+ findKeywords(this.completionToken, singleRef.possibleKeywords, false, false);
+ } else {
+ findTrueOrFalseKeywords(singleRef.possibleKeywords);
+ }
+ }
}
-
}
private void completionOnProvidesInterfacesSingleTypeReference(ASTNode astNode, ASTNode astNodeParent, Binding qualifiedBinding, Scope scope) {
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java
index 4dc9c77d81..27eceba93f 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2021 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -40,6 +40,8 @@ private int kind = K_TYPE;
public boolean isCompletionNode;
public boolean isConstructorType;
public CompletionOnFieldType fieldTypeCompletionNode;
+public char[][] possibleKeywords;
+public boolean canBeExplicitConstructor;
public CompletionOnSingleTypeReference(char[] source, long pos) {
this(source, pos, K_TYPE);
@@ -49,6 +51,11 @@ public CompletionOnSingleTypeReference(char[] source, long pos, int kind) {
this.isCompletionNode = true;
this.kind = kind;
}
+public CompletionOnSingleTypeReference(char[] assistName, long position, char[][] keywords, boolean canBeSuperCall) {
+ this(assistName, position);
+ this.possibleKeywords = keywords;
+ this.canBeExplicitConstructor = canBeSuperCall;
+}
@Override
public void aboutToResolve(Scope scope) {
getTypeBinding(scope);
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 ff22726742..f49c544041 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
@@ -18,6 +18,8 @@
*******************************************************************************/
package org.eclipse.jdt.internal.codeassist.complete;
+import java.util.ArrayList;
+
/*
* Parser able to build specific completion parse nodes, given a cursorLocation.
*
@@ -29,6 +31,7 @@ package org.eclipse.jdt.internal.codeassist.complete;
*/
import java.util.HashSet;
+import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.compiler.CharOperation;
@@ -5130,120 +5133,123 @@ public NameReference createSingleAssistNameReference(char[] assistName, long pos
&& topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == SWITCH) {
return new CompletionOnKeyword3(assistName, position, new char[][]{Keywords.CASE, Keywords.DEFAULT}, false);
} else {
- char[][] keywords = new char[Keywords.COUNT][];
- int count = 0;
+ List<char[]> keywordsList = new ArrayList<>(Keywords.COUNT);
+ canBeExplicitConstructorCall = computeKeywords(kind, keywordsList);
+ char[][] keywords = keywordsList.toArray(char[][]::new);
+ return new CompletionOnSingleNameReference(assistName, position, keywords, canBeExplicitConstructorCall, isInsideAttributeValue());
+ }
+ }
+}
+boolean computeKeywords(int kind, List<char[]> keywords) {
+ boolean canBeExplicitConstructorCall = false;
- if((this.lastModifiers & ClassFileConstants.AccStatic) == 0) {
- keywords[count++]= Keywords.SUPER;
- keywords[count++]= Keywords.THIS;
- }
- keywords[count++]= Keywords.NEW;
- // https://bugs.eclipse.org/bugs/show_bug.cgi?id=269493: Keywords are not proposed in a for
- // loop without block. Completion while at K_CONTROL_STATEMENT_DELIMITER case needs to handled
- // similar to the K_BLOCK_DELIMITER with minor differences.
- if(kind == K_BLOCK_DELIMITER || kind == K_CONTROL_STATEMENT_DELIMITER || kind == K_LAMBDA_EXPRESSION_DELIMITER
- || kind == K_SWITCH_EXPRESSION_DELIMITTER) {
- if(this.canBeExplicitConstructor == YES) {
- canBeExplicitConstructorCall = true;
- }
- if (this.options.complianceLevel >= ClassFileConstants.JDK1_4) {
- keywords[count++]= Keywords.ASSERT;
- }
- keywords[count++]= Keywords.DO;
- keywords[count++]= Keywords.FOR;
- keywords[count++]= Keywords.IF;
- keywords[count++]= Keywords.RETURN;
- keywords[count++]= Keywords.SWITCH;
- keywords[count++]= Keywords.SYNCHRONIZED;
- keywords[count++]= Keywords.THROW;
- keywords[count++]= Keywords.TRY;
- keywords[count++]= Keywords.WHILE;
-
- keywords[count++]= Keywords.FINAL;
- keywords[count++]= Keywords.CLASS;
- if (this.options.complianceLevel >= ClassFileConstants.JDK10) {
- keywords[count++]= Keywords.VAR;
- }
- if (this.options.complianceLevel >= ClassFileConstants.JDK16) {
- keywords[count++]= Keywords.INTERFACE;
- keywords[count++]= Keywords.ENUM;
- }
+ if((this.lastModifiers & ClassFileConstants.AccStatic) == 0) {
+ keywords.add(Keywords.SUPER);
+ keywords.add(Keywords.THIS);
+ }
+ keywords.add(Keywords.NEW);
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=269493: Keywords are not proposed in a for
+ // loop without block. Completion while at K_CONTROL_STATEMENT_DELIMITER case needs to handled
+ // similar to the K_BLOCK_DELIMITER with minor differences.
+ if(kind == K_BLOCK_DELIMITER || kind == K_CONTROL_STATEMENT_DELIMITER || kind == K_LAMBDA_EXPRESSION_DELIMITER
+ || kind == K_SWITCH_EXPRESSION_DELIMITTER) {
+ if(this.canBeExplicitConstructor == YES) {
+ canBeExplicitConstructorCall = true;
+ }
+ if (this.options.complianceLevel >= ClassFileConstants.JDK1_4) {
+ keywords.add(Keywords.ASSERT);
+ }
+ keywords.add(Keywords.DO);
+ keywords.add(Keywords.FOR);
+ keywords.add(Keywords.IF);
+ keywords.add(Keywords.RETURN);
+ keywords.add(Keywords.SWITCH);
+ keywords.add(Keywords.SYNCHRONIZED);
+ keywords.add(Keywords.THROW);
+ keywords.add(Keywords.TRY);
+ keywords.add(Keywords.WHILE);
- if(this.previousKind == K_BLOCK_DELIMITER) {
- switch (this.previousInfo) {
- case IF :
- keywords[count++]= Keywords.ELSE;
- break;
- case CATCH :
- keywords[count++]= Keywords.CATCH;
- keywords[count++]= Keywords.FINALLY;
- break;
- }
- } else if(this.previousKind == K_CONTROL_STATEMENT_DELIMITER && this.previousInfo == IF) {
- keywords[count++]= Keywords.ELSE;
- }
- if(isInsideLoop()) {
- keywords[count++]= Keywords.CONTINUE;
- }
- if(isInsideBreakable()) {
- keywords[count++]= Keywords.BREAK;
- }
- if(isInsideSwitch()) {
- keywords[count++]= Keywords.YIELD;
- }
- } else if (kind == K_BETWEEN_FOR_AND_RIGHT_PAREN) {
- if (this.options.complianceLevel >= ClassFileConstants.JDK10) {
- keywords[count++]= Keywords.VAR;
- }
- } else if(kind != K_BETWEEN_CASE_AND_COLON && kind != K_BETWEEN_DEFAULT_AND_COLON) {
- if (kind == K_LOCAL_INITIALIZER_DELIMITER && this.options.complianceLevel >= ClassFileConstants.JDK11) {
- keywords[count++]= Keywords.VAR;
- }
- if (kind == K_SELECTOR_QUALIFIER && this.options.complianceLevel >= ClassFileConstants.JDK12) {
- keywords[count++] = Keywords.SWITCH;
- }
- keywords[count++]= Keywords.TRUE;
- keywords[count++]= Keywords.FALSE;
- keywords[count++]= Keywords.NULL;
- if (kind == K_YIELD_KEYWORD) {
- keywords[count++]= Keywords.YIELD;
- }
- if(kind == K_SWITCH_LABEL) {
- if(topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) != DEFAULT) {
- keywords[count++]= Keywords.DEFAULT;
- }
- keywords[count++]= Keywords.BREAK;
- keywords[count++]= Keywords.CASE;
- keywords[count++]= Keywords.YIELD;
- if (this.options.complianceLevel >= ClassFileConstants.JDK1_4) {
- keywords[count++]= Keywords.ASSERT;
- }
- keywords[count++]= Keywords.DO;
- keywords[count++]= Keywords.FOR;
- keywords[count++]= Keywords.IF;
- keywords[count++]= Keywords.RETURN;
- keywords[count++]= Keywords.SWITCH;
- keywords[count++]= Keywords.SYNCHRONIZED;
- keywords[count++]= Keywords.THROW;
- keywords[count++]= Keywords.TRY;
- keywords[count++]= Keywords.WHILE;
-
- keywords[count++]= Keywords.FINAL;
- keywords[count++]= Keywords.CLASS;
-
- if (this.options.complianceLevel >= ClassFileConstants.JDK10) {
- keywords[count++]= Keywords.VAR;
- }
- if(isInsideLoop()) {
- keywords[count++]= Keywords.CONTINUE;
- }
- }
- }
- System.arraycopy(keywords, 0 , keywords = new char[count][], 0, count);
+ keywords.add(Keywords.FINAL);
+ keywords.add(Keywords.CLASS);
+ if (this.options.complianceLevel >= ClassFileConstants.JDK10) {
+ keywords.add(Keywords.VAR);
+ }
+ if (this.options.complianceLevel >= ClassFileConstants.JDK16) {
+ keywords.add(Keywords.INTERFACE);
+ keywords.add(Keywords.ENUM);
+ }
- return new CompletionOnSingleNameReference(assistName, position, keywords, canBeExplicitConstructorCall, isInsideAttributeValue());
+ if(this.previousKind == K_BLOCK_DELIMITER) {
+ switch (this.previousInfo) {
+ case IF :
+ keywords.add(Keywords.ELSE);
+ break;
+ case CATCH :
+ keywords.add(Keywords.CATCH);
+ keywords.add(Keywords.FINALLY);
+ break;
+ }
+ } else if(this.previousKind == K_CONTROL_STATEMENT_DELIMITER && this.previousInfo == IF) {
+ keywords.add(Keywords.ELSE);
+ }
+ if(isInsideLoop()) {
+ keywords.add(Keywords.CONTINUE);
+ }
+ if(isInsideBreakable()) {
+ keywords.add(Keywords.BREAK);
+ }
+ if(isInsideSwitch()) {
+ keywords.add(Keywords.YIELD);
+ }
+ } else if (kind == K_BETWEEN_FOR_AND_RIGHT_PAREN) {
+ if (this.options.complianceLevel >= ClassFileConstants.JDK10) {
+ keywords.add(Keywords.VAR);
+ }
+ } else if(kind != K_BETWEEN_CASE_AND_COLON && kind != K_BETWEEN_DEFAULT_AND_COLON) {
+ if (kind == K_LOCAL_INITIALIZER_DELIMITER && this.options.complianceLevel >= ClassFileConstants.JDK11) {
+ keywords.add(Keywords.VAR);
+ }
+ if (kind == K_SELECTOR_QUALIFIER && this.options.complianceLevel >= ClassFileConstants.JDK12) {
+ keywords.add(Keywords.SWITCH);
+ }
+ keywords.add(Keywords.TRUE);
+ keywords.add(Keywords.FALSE);
+ keywords.add(Keywords.NULL);
+ if (kind == K_YIELD_KEYWORD) {
+ keywords.add(Keywords.YIELD);
+ }
+ if(kind == K_SWITCH_LABEL) {
+ if(topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) != DEFAULT) {
+ keywords.add(Keywords.DEFAULT);
+ }
+ keywords.add(Keywords.BREAK);
+ keywords.add(Keywords.CASE);
+ keywords.add(Keywords.YIELD);
+ if (this.options.complianceLevel >= ClassFileConstants.JDK1_4) {
+ keywords.add(Keywords.ASSERT);
+ }
+ keywords.add(Keywords.DO);
+ keywords.add(Keywords.FOR);
+ keywords.add(Keywords.IF);
+ keywords.add(Keywords.RETURN);
+ keywords.add(Keywords.SWITCH);
+ keywords.add(Keywords.SYNCHRONIZED);
+ keywords.add(Keywords.THROW);
+ keywords.add(Keywords.TRY);
+ keywords.add(Keywords.WHILE);
+
+ keywords.add(Keywords.FINAL);
+ keywords.add(Keywords.CLASS);
+
+ if (this.options.complianceLevel >= ClassFileConstants.JDK10) {
+ keywords.add(Keywords.VAR);
+ }
+ if(isInsideLoop()) {
+ keywords.add(Keywords.CONTINUE);
+ }
}
}
+ return canBeExplicitConstructorCall;
}
private TypeReference checkAndCreateModuleSingleAssistTypeReference(char[] assistName, long position) {
if (isInUsesStatement()) return new CompletionOnUsesSingleTypeReference(assistName, position);
@@ -5251,7 +5257,9 @@ private TypeReference checkAndCreateModuleSingleAssistTypeReference(char[] assis
if (isAfterWithClause()) return new CompletionOnProvidesImplementationsSingleTypeReference(assistName, position);
return new CompletionOnProvidesInterfacesSingleTypeReference(assistName, position);
}
- return new CompletionOnSingleTypeReference(assistName,position);
+ List<char[]> keywords = new ArrayList<>(Keywords.COUNT);
+ boolean canBeCtorCall = computeKeywords(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER), keywords);
+ return new CompletionOnSingleTypeReference(assistName,position, keywords.toArray(char[][]::new), canBeCtorCall);
}
@Override
public TypeReference createSingleAssistTypeReference(char[] assistName, long position) {

Back to the top