### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core Index: codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java,v retrieving revision 1.213 diff -u -r1.213 CompletionParser.java --- codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java 21 Apr 2010 12:06:14 -0000 1.213 +++ codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java 22 Apr 2010 06:56:14 -0000 @@ -80,6 +80,9 @@ protected static final int K_CONTROL_STATEMENT_DELIMITER = COMPLETION_PARSER + 38; protected static final int K_INSIDE_ASSERT_EXCEPTION = COMPLETION_PARSER + 39; protected static final int K_INSIDE_FOR_CONDITIONAL = COMPLETION_PARSER + 40; + // added for https://bugs.eclipse.org/bugs/show_bug.cgi?id=261534 + protected static final int K_BETWEEN_INSTANCEOF_AND_RPAREN = COMPLETION_PARSER + 41; + public final static char[] FAKE_TYPE_NAME = new char[]{' '}; public final static char[] FAKE_METHOD_NAME = new char[]{' '}; @@ -563,7 +566,9 @@ && ((this.expressionPtr > 0 && this.expressionStack[this.expressionPtr - 1] instanceof InstanceOfExpression) || (this.elementPtr >= 0 && this.elementObjectInfoStack[this.elementPtr] instanceof InstanceOfExpression))) || (expression instanceof AllocationExpression - && ((AllocationExpression)expression).type == this.assistNode)){ + && ((AllocationExpression)expression).type == this.assistNode) + || (expression instanceof BinaryExpression + && (this.elementPtr >= 0 && this.elementObjectInfoStack[this.elementPtr] instanceof InstanceOfExpression))){ buildMoreCompletionContext(expression); if (this.assistNodeParent == null && expression instanceof Assignment) { @@ -1062,8 +1067,17 @@ int blockIndex = lastIndexOfElement(K_BLOCK_DELIMITER); int controlIndex = lastIndexOfElement(K_CONTROL_STATEMENT_DELIMITER); - int index = blockIndex != -1 && controlIndex < blockIndex ? blockIndex : controlIndex; - + int index; + if (controlIndex != -1) { + index = blockIndex != -1 && controlIndex < blockIndex ? blockIndex : controlIndex; + } + else { + // To handle the case when the completion is requested before enclosing R_PAREN + // and an instanceof expression is also present + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=261534 + int instanceOfIndex = lastIndexOfElement(K_BETWEEN_INSTANCEOF_AND_RPAREN); + index = blockIndex != -1 && instanceOfIndex < blockIndex ? blockIndex : instanceOfIndex; + } if (index != -1 && this.elementInfoStack[index] == IF && this.elementObjectInfoStack[index] != null) { Expression condition = (Expression)this.elementObjectInfoStack[index]; @@ -1086,7 +1100,9 @@ } } - + if (statement instanceof BinaryExpression && this.assistNode instanceof Statement) { + statement = (Statement) this.assistNode; + } IfStatement ifStatement = new IfStatement( condition, @@ -2606,6 +2622,10 @@ protected void consumeInstanceOfExpression() { super.consumeInstanceOfExpression(); popElement(K_BINARY_OPERATOR); + // to handle https://bugs.eclipse.org/bugs/show_bug.cgi?id=261534 + if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BETWEEN_IF_AND_RIGHT_PAREN) { + pushOnElementStack(K_BETWEEN_INSTANCEOF_AND_RPAREN, IF, this.expressionStack[this.expressionPtr]); + } InstanceOfExpression exp = (InstanceOfExpression) this.expressionStack[this.expressionPtr]; if(this.assistNode != null && exp.type == this.assistNode) { @@ -3444,6 +3464,9 @@ case K_BETWEEN_CATCH_AND_RIGHT_PAREN : popElement(K_BETWEEN_CATCH_AND_RIGHT_PAREN); break; + case K_BETWEEN_INSTANCEOF_AND_RPAREN : + popElement(K_BETWEEN_INSTANCEOF_AND_RPAREN); + //$FALL-THROUGH$ case K_BETWEEN_IF_AND_RIGHT_PAREN : if(topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == this.bracketDepth) { popElement(K_BETWEEN_IF_AND_RIGHT_PAREN); #P org.eclipse.jdt.core.tests.model Index: src/org/eclipse/jdt/core/tests/model/CompletionTests.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests.java,v retrieving revision 1.217 diff -u -r1.217 CompletionTests.java --- src/org/eclipse/jdt/core/tests/model/CompletionTests.java 22 Apr 2010 04:39:17 -0000 1.217 +++ src/org/eclipse/jdt/core/tests/model/CompletionTests.java 22 Apr 2010 06:56:48 -0000 @@ -21186,4 +21186,46 @@ "AClass[TYPE_REF]{AClass, test, Ltest.AClass;, null, null, 27}", requestor.getResults()); } + +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=261534 +// To verify that autocast works correctly even when instanceof expression +// and completion node are in the same binary expression, related by && +public void testBug261534() throws JavaModelException { + this.workingCopies = new ICompilationUnit[1]; + this.workingCopies[0] = getWorkingCopy( + "/Completion/src/test/CompletionAfterInstanceOf.java", + "package test;" + + "class MyString {\n" + + " public String toWelcome() {\n" + + " return \"welcome\";\n" + + " }\n" + + "}\n" + + "public class CompletionAfterInstanceOf {\n" + + " void foo() {\n" + + " Object chars= null;\n" + + " if (chars instanceof MyString && chars.to) {\n" + + " }\n" + + " }\n" + + "}\n"); + + CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true, true, true, true, true, true); + requestor.allowAllRequiredProposals(); + String str = this.workingCopies[0].getSource(); + String completeBehind = "chars instanceof MyString && chars.to"; + int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); + this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner); + + int relevance1 = R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_NON_STATIC + R_NON_RESTRICTED; + int start1 = str.lastIndexOf("to") + "".length(); + int end1 = start1 + "to".length(); + int start2 = str.lastIndexOf("chars.to"); + int end2 = start2 + "chars.to".length(); + int start3 = str.lastIndexOf("chars."); + int end3 = start3 + "chars".length(); + + assertResults( + "toString[METHOD_REF]{toString(), Ljava.lang.Object;, ()Ljava.lang.String;, null, null, toString, null, replace[" + start1 + ", " + end1 + "], token[" + start1 + ", " + end1 +"], " + relevance1 + "}\n" + + "toWelcome[METHOD_REF_WITH_CASTED_RECEIVER]{((MyString)chars).toWelcome(), Ltest.MyString;, ()Ljava.lang.String;, Ltest.MyString;, null, null, toWelcome, null, replace[" + start2 +", " + end2 + "], token[" + start1 + ", " + end1 + "], receiver[" + start3 + ", " + end3 + "], " + relevance1 + "}", + requestor.getResults()); +} }