Skip to content

Commit 8da54fe

Browse files
datho7561rgrunber
authored andcommitted
Many keyword completion fixes
- Completion for `new`, `final`, `true`, `false`, and `null` keywords - Improve logic for checking if only expression-like keywords should be suggested - Prevent default completions in switches without a case label/default label Signed-off-by: David Thompson <[email protected]>
1 parent a1b1bc7 commit 8da54fe

File tree

1 file changed

+66
-8
lines changed

1 file changed

+66
-8
lines changed

org.eclipse.jdt.core.javac/src/org/eclipse/jdt/internal/codeassist/DOMCompletionEngine.java

Lines changed: 66 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
import org.eclipse.jdt.core.dom.Annotation;
7171
import org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration;
7272
import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
73+
import org.eclipse.jdt.core.dom.Assignment;
7374
import org.eclipse.jdt.core.dom.Block;
7475
import org.eclipse.jdt.core.dom.CatchClause;
7576
import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor;
@@ -687,6 +688,13 @@ public void complete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit sour
687688
if (!fieldAccessType.isRecovered()) {
688689
processMembers(fieldAccess, fieldAccessExpr.resolveTypeBinding(), specificCompletionBindings, false);
689690
publishFromScope(specificCompletionBindings);
691+
if (fieldAccessExpr instanceof ThisExpression) {
692+
// this.new can be used to instantiate non-static inner classes
693+
// eg. MyInner myInner = this.new MyInner(12);
694+
if (CharOperation.prefixEquals(this.prefix.toCharArray(), Keywords.NEW)) {
695+
this.requestor.accept(createKeywordProposal(Keywords.NEW, -1, -1));
696+
}
697+
}
690698
IVariableBinding variableToCast = null;
691699
if (fieldAccessExpr instanceof Name name && name.resolveBinding() instanceof IVariableBinding variableBinding) {
692700
variableToCast = variableBinding;
@@ -1011,6 +1019,8 @@ public void complete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit sour
10111019
// }
10121020
ITypeBinding typeDeclBinding = typeDecl.resolveBinding();
10131021
findOverridableMethods(typeDeclBinding, this.javaProject, null);
1022+
suggestTypeKeywords(true);
1023+
suggestModifierKeywords(0);
10141024
}
10151025
}
10161026
suggestDefaultCompletions = false;
@@ -1843,14 +1853,29 @@ public void complete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit sour
18431853
}
18441854
if (context instanceof SwitchStatement || context instanceof SwitchExpression) {
18451855
boolean hasDefault = false;
1856+
boolean afterLabel = false;
18461857
if (context instanceof SwitchStatement switchStatement) {
1847-
hasDefault = switchStatement.statements().stream().anyMatch(statement -> {
1848-
return statement instanceof SwitchCase switchCase && switchCase.isDefault();
1849-
});
1858+
for (Statement statement : (List<Statement>)switchStatement.statements()) {
1859+
if (statement instanceof SwitchCase switchCase) {
1860+
if (switchCase.isDefault()) {
1861+
hasDefault = true;
1862+
}
1863+
if (switchCase.getStartPosition() < this.offset) {
1864+
afterLabel = true;
1865+
}
1866+
}
1867+
}
18501868
} else {
1851-
hasDefault = ((SwitchExpression)context).statements().stream().anyMatch(statement -> {
1852-
return statement instanceof SwitchCase switchCase && switchCase.isDefault();
1853-
});
1869+
for (Statement statement : (List<Statement>)((SwitchExpression)context).statements()) {
1870+
if (statement instanceof SwitchCase switchCase) {
1871+
if (switchCase.isDefault()) {
1872+
hasDefault = true;
1873+
}
1874+
if (switchCase.getStartPosition() < this.offset) {
1875+
afterLabel = true;
1876+
}
1877+
}
1878+
}
18541879
}
18551880
if (!this.isFailedMatch(this.prefix.toCharArray(), Keywords.CASE)) {
18561881
this.requestor.accept(createKeywordProposal(Keywords.CASE, -1, -1));
@@ -1860,6 +1885,10 @@ public void complete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit sour
18601885
this.requestor.accept(createKeywordProposal(Keywords.DEFAULT, -1, -1));
18611886
}
18621887
}
1888+
if (!afterLabel) {
1889+
// case or default label required before regular body statements
1890+
suggestDefaultCompletions = false;
1891+
}
18631892
}
18641893
if (context != null && context.getLocationInParent() == QualifiedType.NAME_PROPERTY && context.getParent() instanceof QualifiedType qType) {
18651894
Type qualifier = qType.getQualifier();
@@ -2860,9 +2889,19 @@ private void checkCancelled() {
28602889

28612890
private void statementLikeKeywords() {
28622891
List<char[]> keywords = new ArrayList<>();
2863-
boolean isExpressionExpected = (this.toComplete.getParent() instanceof IfStatement ifStatement
2892+
boolean isExpressionExpected =
2893+
(this.toComplete.getParent() instanceof IfStatement ifStatement
28642894
&& (IfStatement.EXPRESSION_PROPERTY.getId().equals(this.toComplete.getLocationInParent().getId())
2865-
|| "$missing$".equals(ifStatement.getExpression().toString())));
2895+
|| "$missing$".equals(ifStatement.getExpression().toString())))
2896+
||
2897+
(this.toComplete.getParent() instanceof WhileStatement whileStatement
2898+
&& (WhileStatement.EXPRESSION_PROPERTY.getId().equals(this.toComplete.getLocationInParent().getId())
2899+
|| "$missing$".equals(whileStatement.getExpression().toString())))
2900+
||
2901+
(this.toComplete.getParent() instanceof Assignment)
2902+
||
2903+
(this.toComplete instanceof Assignment)
2904+
;
28662905
if (!isExpressionExpected) {
28672906
keywords.add(Keywords.ASSERT);
28682907
keywords.add(Keywords.RETURN);
@@ -2874,8 +2913,14 @@ private void statementLikeKeywords() {
28742913
keywords.add(Keywords.SYNCHRONIZED);
28752914
keywords.add(Keywords.THROW);
28762915
keywords.add(Keywords.TRY);
2916+
keywords.add(Keywords.FINAL);
28772917
}
28782918
keywords.add(Keywords.SUPER);
2919+
keywords.add(Keywords.NEW);
2920+
2921+
if (!this.expectedTypes.getExpectedTypes().isEmpty()) {
2922+
keywords.add(Keywords.NULL);
2923+
}
28792924
if (DOMCompletionUtil.findParent(this.toComplete,
28802925
new int[] { ASTNode.WHILE_STATEMENT, ASTNode.DO_STATEMENT, ASTNode.FOR_STATEMENT }) != null) {
28812926
if (!isExpressionExpected) {
@@ -2919,6 +2964,19 @@ private void statementLikeKeywords() {
29192964
this.requestor.accept(createKeywordProposal(keyword, this.toComplete.getStartPosition(), this.offset));
29202965
}
29212966
}
2967+
// Z means boolean
2968+
if (this.expectedTypes.getExpectedTypes().stream().anyMatch(type -> "Z".equals(type.getKey()))) {
2969+
if (!isFailedMatch(this.prefix.toCharArray(), Keywords.TRUE)) {
2970+
CompletionProposal completionProposal = createKeywordProposal(Keywords.TRUE, this.toComplete.getStartPosition(), this.offset);
2971+
completionProposal.setRelevance(completionProposal.getRelevance() + RelevanceConstants.R_EXACT_EXPECTED_TYPE + RelevanceConstants.R_UNQUALIFIED);
2972+
this.requestor.accept(completionProposal);
2973+
}
2974+
if (!isFailedMatch(this.prefix.toCharArray(), Keywords.FALSE)) {
2975+
CompletionProposal completionProposal = createKeywordProposal(Keywords.FALSE, this.toComplete.getStartPosition(), this.offset);
2976+
completionProposal.setRelevance(completionProposal.getRelevance() + RelevanceConstants.R_EXACT_EXPECTED_TYPE + RelevanceConstants.R_UNQUALIFIED);
2977+
this.requestor.accept(completionProposal);
2978+
}
2979+
}
29222980
}
29232981

29242982
private void completeJavadocBlockTags(TagElement tagNode) {

0 commit comments

Comments
 (0)