Skip to content

Commit 083f424

Browse files
datho7561rgrunber
authored andcommitted
Keyword completion fixes for try/catch/finally and do-while
- Disable default completion in completion after a try statement without a catch or finally - Complete `catch` and `finally` after try statements (do not suggest `finally` if there's already a `finally` statement) - Suggest `while` after a do-while statement if it's missing - Prevent default completion after a do-while statement if it's missing the `while` keyword Signed-off-by: David Thompson <[email protected]>
1 parent ea5fe31 commit 083f424

File tree

1 file changed

+69
-5
lines changed

1 file changed

+69
-5
lines changed

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

Lines changed: 69 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
7979
import org.eclipse.jdt.core.dom.Comment;
8080
import org.eclipse.jdt.core.dom.CompilationUnit;
81+
import org.eclipse.jdt.core.dom.DoStatement;
8182
import org.eclipse.jdt.core.dom.EnhancedForStatement;
8283
import org.eclipse.jdt.core.dom.EnumDeclaration;
8384
import org.eclipse.jdt.core.dom.Expression;
@@ -630,8 +631,11 @@ public void complete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit sour
630631
} else if (simpleType.getName() instanceof QualifiedName qualifiedName) {
631632
context = qualifiedName;
632633
}
633-
} else if (this.toComplete instanceof Block block && this.offset == block.getStartPosition()) {
634-
context = this.toComplete.getParent();
634+
} else if (this.toComplete instanceof Block block) {
635+
if (this.offset == block.getStartPosition()
636+
|| this.offset >= block.getStartPosition() + block.getLength()) {
637+
context = this.toComplete.getParent();
638+
}
635639
} else if (this.toComplete instanceof StringLiteral stringLiteral && (this.offset <= stringLiteral.getStartPosition() || stringLiteral.getStartPosition() + stringLiteral.getLength() <= this.offset)) {
636640
context = stringLiteral.getParent();
637641
} else if (this.toComplete instanceof VariableDeclaration vd) {
@@ -788,6 +792,9 @@ public void complete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit sour
788792
// }
789793
ITypeBinding typeDeclBinding = typeDecl.resolveBinding();
790794
findOverridableMethods(typeDeclBinding, this.javaProject, context);
795+
if (!isFailedMatch(this.prefix.toCharArray(), Keywords.CLASS)) {
796+
this.requestor.accept(createKeywordProposal(Keywords.CLASS, this.toComplete.getStartPosition(), this.offset));
797+
}
791798
suggestTypeKeywords(true);
792799
suggestModifierKeywords(fieldDeclaration.getModifiers());
793800
if (!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
@@ -832,6 +839,18 @@ public void complete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit sour
832839
}
833840
suggestDefaultCompletions = false;
834841
}
842+
if (context.getParent() instanceof DoStatement doStatement) {
843+
if (doStatement.getBody().getStartPosition() + doStatement.getBody().getLength() < this.offset) {
844+
String needsWhileTextArea = this.textContent.substring(doStatement.getBody().getStartPosition() + doStatement.getBody().getLength(),
845+
doStatement.getStartPosition() + doStatement.getLength());
846+
if (!needsWhileTextArea.contains("while")) {
847+
if (!isFailedMatch(this.prefix.toCharArray(), Keywords.WHILE)) {
848+
this.requestor.accept(createKeywordProposal(Keywords.WHILE, -1, -1));
849+
}
850+
suggestDefaultCompletions = false;
851+
}
852+
}
853+
}
835854
if (context.getParent() instanceof MarkerAnnotation) {
836855
completeMarkerAnnotation(completeAfter);
837856
suggestDefaultCompletions = false;
@@ -1818,6 +1837,21 @@ public void complete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit sour
18181837
suggestDefaultCompletions = false;
18191838
}
18201839
}
1840+
if (context instanceof TryStatement tryStatement) {
1841+
if (tryStatement.getBody().getStartPosition() + tryStatement.getBody().getLength() < this.offset) {
1842+
if (tryStatement.getFinally() == null) {
1843+
if (!isFailedMatch(this.prefix.toCharArray(), Keywords.FINALLY)) {
1844+
this.requestor.accept(createKeywordProposal(Keywords.FINALLY, -1, -1));
1845+
}
1846+
}
1847+
if (!isFailedMatch(this.prefix.toCharArray(), Keywords.CATCH)) {
1848+
this.requestor.accept(createKeywordProposal(Keywords.CATCH, -1, -1));
1849+
}
1850+
if (tryStatement.getFinally() == null && tryStatement.catchClauses().isEmpty()) {
1851+
suggestDefaultCompletions = false;
1852+
}
1853+
}
1854+
}
18211855
if (context instanceof CompilationUnit) {
18221856
// recover existing modifiers (they can't exist in the DOM since there is no TypeDeclaration)
18231857
boolean afterBrokenImport = false;
@@ -1829,7 +1863,7 @@ public void complete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit sour
18291863
ImportDeclaration lastImport = (ImportDeclaration)this.unit.imports().get(this.unit.imports().size() - 1);
18301864
startOffset = lastImport.getStartPosition() + lastImport.getLength();
18311865

1832-
if (lastImport.getName().toString().endsWith("$missing$")) {
1866+
if (lastImport.getName().toString().endsWith(FAKE_IDENTIFIER)) {
18331867
afterBrokenImport = true;
18341868
}
18351869
}
@@ -1901,6 +1935,35 @@ public void complete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit sour
19011935
}
19021936
}
19031937
}
1938+
{
1939+
// If the completion is after a try block without a catch or finally,
1940+
// we need to disable default completion.
1941+
ASTNode cursor = this.toComplete;
1942+
ASTNode parentCursor = this.toComplete.getParent();
1943+
while (parentCursor != null && !(parentCursor instanceof Block)) {
1944+
cursor = parentCursor;
1945+
parentCursor = parentCursor.getParent();
1946+
}
1947+
if (parentCursor instanceof Block parentBlock) {
1948+
int statementIndex = parentBlock.statements().indexOf(cursor);
1949+
if (statementIndex > 0) {
1950+
Statement prevStatement = ((List<Statement>)parentBlock.statements()).get(statementIndex - 1);
1951+
if (prevStatement instanceof TryStatement tryStatement) {
1952+
if (!isFailedMatch(this.prefix.toCharArray(), Keywords.CATCH)) {
1953+
this.requestor.accept(createKeywordProposal(Keywords.CATCH, -1, -1));
1954+
}
1955+
if (tryStatement.getFinally() == null) {
1956+
if (!isFailedMatch(this.prefix.toCharArray(), Keywords.FINALLY)) {
1957+
this.requestor.accept(createKeywordProposal(Keywords.FINALLY, -1, -1));
1958+
}
1959+
}
1960+
if (tryStatement.catchClauses().isEmpty() && tryStatement.getFinally() == null) {
1961+
suggestDefaultCompletions = false;
1962+
}
1963+
}
1964+
}
1965+
}
1966+
}
19041967
if (isParameterInNonParameterizedType(context)) {
19051968
suggestDefaultCompletions = false;
19061969
}
@@ -2892,11 +2955,11 @@ private void statementLikeKeywords() {
28922955
boolean isExpressionExpected =
28932956
(this.toComplete.getParent() instanceof IfStatement ifStatement
28942957
&& (IfStatement.EXPRESSION_PROPERTY.getId().equals(this.toComplete.getLocationInParent().getId())
2895-
|| "$missing$".equals(ifStatement.getExpression().toString())))
2958+
|| FAKE_IDENTIFIER.equals(ifStatement.getExpression().toString())))
28962959
||
28972960
(this.toComplete.getParent() instanceof WhileStatement whileStatement
28982961
&& (WhileStatement.EXPRESSION_PROPERTY.getId().equals(this.toComplete.getLocationInParent().getId())
2899-
|| "$missing$".equals(whileStatement.getExpression().toString())))
2962+
|| FAKE_IDENTIFIER.equals(whileStatement.getExpression().toString())))
29002963
||
29012964
(this.toComplete.getParent() instanceof Assignment)
29022965
||
@@ -2914,6 +2977,7 @@ private void statementLikeKeywords() {
29142977
keywords.add(Keywords.THROW);
29152978
keywords.add(Keywords.TRY);
29162979
keywords.add(Keywords.FINAL);
2980+
keywords.add(Keywords.CLASS);
29172981
}
29182982
keywords.add(Keywords.SUPER);
29192983
keywords.add(Keywords.NEW);

0 commit comments

Comments
 (0)