Skip to content

Commit

Permalink
completion returns no results with pattern matching
Browse files Browse the repository at this point in the history
  • Loading branch information
snjeza committed Nov 20, 2024
1 parent 6b53bf4 commit 3cc6c0b
Show file tree
Hide file tree
Showing 2 changed files with 167 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -524,4 +524,130 @@ public final class SqlStorage extends Storage {
SqlStorage[TYPE_REF]{SqlStorage, , LSqlStorage;, null, null, 52}\
""", requestor.getResults());
}
// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/2106
public void testGH2106() throws JavaModelException {
this.workingCopies = new ICompilationUnit[1];
this.workingCopies[0] = getWorkingCopy(
"/Completion/src/X.java",
"""
import java.util.ArrayList;
import java.util.List;
public class X {
public static void main(String[] args) {
Object unknown = "abc";
if (unknown instanceof String str) {
str.le
Object nothing = null;
str.le
}
}
}
""");
CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true);
requestor.allowAllRequiredProposals();
String str = this.workingCopies[0].getSource();
String completeBehind = "str.le";
int cursorLocation = str.indexOf(completeBehind) + completeBehind.length();
this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
assertResults("length[METHOD_REF]{length(), Ljava.lang.String;, ()I, length, null, 60}",
requestor.getResults());
}
public void testGH2106a() throws JavaModelException {
this.workingCopies = new ICompilationUnit[1];
this.workingCopies[0] = getWorkingCopy(
"/Completion/src/X.java",
"""
import java.util.ArrayList;
import java.util.List;
public class X {
public static void main(String[] args) {
Object unknown = "abc";
if (unknown instanceof String str) {
str.
Object nothing = null;
str.
}
}
}
""");
CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true);
requestor.allowAllRequiredProposals();
String str = this.workingCopies[0].getSource();
String completeBehind = "str.";
int cursorLocation = str.indexOf(completeBehind) + completeBehind.length();
this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
assertResults("clone[METHOD_REF]{clone(), Ljava.lang.Object;, ()Ljava.lang.Object;, clone, null, 60}\n"
+ "codePointAt[METHOD_REF]{codePointAt(), Ljava.lang.String;, (I)I, codePointAt, (index), 60}\n"
+ "equals[METHOD_REF]{equals(), Ljava.lang.Object;, (Ljava.lang.Object;)Z, equals, (obj), 60}\n"
+ "finalize[METHOD_REF]{finalize(), Ljava.lang.Object;, ()V, finalize, null, 60}\n"
+ "getClass[METHOD_REF]{getClass(), Ljava.lang.Object;, ()Ljava.lang.Class<+Ljava.lang.Object;>;, getClass, null, 60}\n"
+ "hashCode[METHOD_REF]{hashCode(), Ljava.lang.Object;, ()I, hashCode, null, 60}\n"
+ "length[METHOD_REF]{length(), Ljava.lang.String;, ()I, length, null, 60}\n"
+ "notify[METHOD_REF]{notify(), Ljava.lang.Object;, ()V, notify, null, 60}\n"
+ "notifyAll[METHOD_REF]{notifyAll(), Ljava.lang.Object;, ()V, notifyAll, null, 60}\n"
+ "toString[METHOD_REF]{toString(), Ljava.lang.Object;, ()Ljava.lang.String;, toString, null, 60}\n"
+ "wait[METHOD_REF]{wait(), Ljava.lang.Object;, ()V, wait, null, 60}\n"
+ "wait[METHOD_REF]{wait(), Ljava.lang.Object;, (J)V, wait, (millis), 60}\n"
+ "wait[METHOD_REF]{wait(), Ljava.lang.Object;, (JI)V, wait, (millis, nanos), 60}",
requestor.getResults());
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=568934#c6
public void testGH2106b() throws JavaModelException {
this.workingCopies = new ICompilationUnit[1];
this.workingCopies[0] = getWorkingCopy(
"/Completion/src/X.java",
"""
public class X {
public static void main(String[] args) {
Object o = new Object();
if(o instanceof X mc) {
mc.
System.out.println("hello "+mc.);
}
}
}
""");
CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true);
requestor.allowAllRequiredProposals();
String str = this.workingCopies[0].getSource();
String completeBehind = "mc.";
int cursorLocation = str.indexOf(completeBehind) + completeBehind.length();
this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
assertResults("main[METHOD_REF]{main(), LX;, ([Ljava.lang.String;)V, main, (args), 49}\n"
+ "clone[METHOD_REF]{clone(), Ljava.lang.Object;, ()Ljava.lang.Object;, clone, null, 60}\n"
+ "equals[METHOD_REF]{equals(), Ljava.lang.Object;, (Ljava.lang.Object;)Z, equals, (obj), 60}\n"
+ "finalize[METHOD_REF]{finalize(), Ljava.lang.Object;, ()V, finalize, null, 60}\n"
+ "getClass[METHOD_REF]{getClass(), Ljava.lang.Object;, ()Ljava.lang.Class<+Ljava.lang.Object;>;, getClass, null, 60}\n"
+ "hashCode[METHOD_REF]{hashCode(), Ljava.lang.Object;, ()I, hashCode, null, 60}\n"
+ "notify[METHOD_REF]{notify(), Ljava.lang.Object;, ()V, notify, null, 60}\n"
+ "notifyAll[METHOD_REF]{notifyAll(), Ljava.lang.Object;, ()V, notifyAll, null, 60}\n"
+ "toString[METHOD_REF]{toString(), Ljava.lang.Object;, ()Ljava.lang.String;, toString, null, 60}\n"
+ "wait[METHOD_REF]{wait(), Ljava.lang.Object;, ()V, wait, null, 60}\n"
+ "wait[METHOD_REF]{wait(), Ljava.lang.Object;, (J)V, wait, (millis), 60}\n"
+ "wait[METHOD_REF]{wait(), Ljava.lang.Object;, (JI)V, wait, (millis, nanos), 60}",
requestor.getResults());
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=568934#c8
public void testGH2106c() throws JavaModelException {
this.workingCopies = new ICompilationUnit[1];
this.workingCopies[0] = getWorkingCopy(
"/Completion/src/X.java",
"""
class X {
int x, y;
public boolean equals(Object o) {
return o instanceof X other && this.x == oth // content assist here gives the issues
}
}
""");
CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true);
requestor.allowAllRequiredProposals();
String str = this.workingCopies[0].getSource();
String completeBehind = "oth";
int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
assertResults("other[LOCAL_VARIABLE_REF]{other, null, LX;, other, null, 52}",
requestor.getResults());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -653,8 +653,8 @@ protected void attachOrphanCompletionNode(){
|| (this.elementPtr >= 0 && stackHasInstanceOfExpression(this.elementObjectInfoStack, this.elementPtr))))
|| (expression instanceof AllocationExpression
&& ((AllocationExpression)expression).type == this.assistNode)
|| (expression instanceof AND_AND_Expression
&& (this.elementPtr >= 0 && this.elementObjectInfoStack[this.elementPtr] instanceof InstanceOfExpression))
|| (expression instanceof AND_AND_Expression // https://bugs.eclipse.org/bugs/show_bug.cgi?id=568934#c8
&& (this.elementPtr >= 0 && (this.elementObjectInfoStack[this.elementPtr] == null || this.elementObjectInfoStack[this.elementPtr] instanceof InstanceOfExpression)))
|| (expression instanceof ConditionalExpression
&& ((ConditionalExpression) expression).valueIfFalse == this.assistNode)){
buildMoreCompletionContext(expression);
Expand All @@ -674,22 +674,50 @@ protected void attachOrphanCompletionNode(){
}
}
}
if (this.astPtr > -1 && this.astStack[this.astPtr] instanceof LocalDeclaration) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=287939
// To take care of: if (a instance of X) int i = a.|
LocalDeclaration local = (LocalDeclaration) this.astStack[this.astPtr];
if (local.initialization == this.assistNode) {
Statement enclosing = buildMoreCompletionEnclosingContext(local);
if (enclosing instanceof IfStatement) {
if (this.currentElement instanceof RecoveredBlock) {
// RecoveredLocalVariable must be removed from its parent because the IfStatement will be added instead
RecoveredBlock recoveredBlock = (RecoveredBlock) this.currentElement;
recoveredBlock.statements[--recoveredBlock.statementCount] = null;
this.currentElement = this.currentElement.add(enclosing, 0);
LocalDeclaration local = getLocalDeclarationFromAstStack();
if (local != null) {
Statement enclosing = buildMoreCompletionEnclosingContext(local);
if (enclosing instanceof IfStatement ifStatement) {
if (this.currentElement instanceof RecoveredBlock recoveredBlock) {
// RecoveredLocalVariable must be removed from its parent because the IfStatement will be added instead
RecoveredStatement[] statements = new RecoveredStatement[recoveredBlock.statementCount - 1];
int j = 0;
for (int i = 0; i < recoveredBlock.statementCount; i++) {
RecoveredStatement statement = recoveredBlock.statements[i];
if ( !(statement instanceof RecoveredLocalVariable recoveredLocalVariable && recoveredLocalVariable.localDeclaration == local)) {
statements[j++] = statement;
}
}
for (int i = 0; i < statements.length; i++) {
recoveredBlock.statements[i] = statements[i];
}
recoveredBlock.statements[--recoveredBlock.statementCount] = null;
// if (a instanceof List l) { l.is| Object // https://github.com/eclipse-jdt/eclipse.jdt.core/issues/2106
if (ifStatement.condition instanceof InstanceOfExpression iof && iof.pattern instanceof TypePattern pattern) {
this.currentElement.add(pattern.local, 0);
}
this.currentElement = this.currentElement.add(ifStatement, 0);
}
}
}
}
private LocalDeclaration getLocalDeclarationFromAstStack() {
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=287939
// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/2106
int ptr = this.astPtr;
while (ptr > -1) {
// To take care of: if (a instance of X) int i = a.|
// if (a instanceof List l) { l.is| Object
// if (a instanceof List l) { l.| Object // https://github.com/eclipse-jdt/eclipse.jdt.core/issues/2106
if (this.astStack[ptr] instanceof LocalDeclaration local) {
if (local.initialization == this.assistNode || local.type == this.assistNode) {
return local;
}
}
ptr--;
}
return null;
}

private static class SavedState {
final ASTNode assistNodeParent;
Expand Down

0 comments on commit 3cc6c0b

Please sign in to comment.