Skip to content

Commit

Permalink
completion returns no results with pattern matching
Browse files Browse the repository at this point in the history
Signed-off-by: Snjezana Peco <snjezana.peco@redhat.com>
  • Loading branch information
snjeza committed Apr 2, 2024
1 parent e53e413 commit bd43fb9
Show file tree
Hide file tree
Showing 2 changed files with 169 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -705,4 +705,130 @@ public void testIssue92() throws JavaModelException {
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 @@ -105,6 +105,7 @@
import org.eclipse.jdt.internal.compiler.ast.TryStatement;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
import org.eclipse.jdt.internal.compiler.ast.TypePattern;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.ast.UnaryExpression;
import org.eclipse.jdt.internal.compiler.ast.UnionTypeReference;
Expand All @@ -126,6 +127,7 @@
import org.eclipse.jdt.internal.compiler.parser.RecoveredModule;
import org.eclipse.jdt.internal.compiler.parser.RecoveredPackageVisibilityStatement;
import org.eclipse.jdt.internal.compiler.parser.RecoveredProvidesStatement;
import org.eclipse.jdt.internal.compiler.parser.RecoveredStatement;
import org.eclipse.jdt.internal.compiler.parser.RecoveredType;
import org.eclipse.jdt.internal.compiler.parser.RecoveredUnit;
import org.eclipse.jdt.internal.compiler.parser.Scanner;
Expand Down Expand Up @@ -734,8 +736,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 @@ -755,22 +757,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 bd43fb9

Please sign in to comment.