### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core Index: codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java,v retrieving revision 1.413 diff -u -r1.413 CompletionEngine.java --- codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java 21 Jun 2010 07:52:34 -0000 1.413 +++ codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java 21 Jun 2010 12:02:18 -0000 @@ -523,6 +523,7 @@ boolean assistNodeIsInterfaceExcludingAnnotation; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=310423 int assistNodeInJavadoc = 0; boolean assistNodeCanBeSingleMemberAnnotation = false; + boolean assistNodeIsInsideCase = false; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=195346 long targetedElement; @@ -2860,6 +2861,21 @@ return false; } + private boolean assistNodeIsInsideCase(ASTNode astNode, ASTNode astNodeParent) { + // To find whether we're completing inside the case expression in a + // switch case construct (https://bugs.eclipse.org/bugs/show_bug.cgi?id=195346) + if (astNodeParent instanceof SwitchStatement) { + CaseStatement[] cases = ((SwitchStatement) astNodeParent).cases; + for (int i = 0, caseCount = ((SwitchStatement) astNodeParent).caseCount; i < caseCount; i++) { + CompletionNodeDetector detector = new CompletionNodeDetector(astNode, cases[i]); + if (detector.containsCompletionNode()) { + return true; + } + } + } + return false; + } + private void completionOnQualifiedAllocationExpression(ASTNode astNode, Binding qualifiedBinding, Scope scope) { setSourceAndTokenRange(astNode.sourceStart, astNode.sourceEnd, false); @@ -2916,6 +2932,7 @@ (CompletionOnQualifiedNameReference) astNode; this.completionToken = ref.completionIdentifier; long completionPosition = ref.sourcePositions[ref.sourcePositions.length - 1]; + this.assistNodeIsInsideCase = assistNodeIsInsideCase(astNode, this.parser.assistNodeParent); if (qualifiedBinding.problemId() == ProblemReasons.NotFound) { setSourceAndTokenRange((int) (completionPosition >>> 32), (int) completionPosition); @@ -3060,7 +3077,8 @@ this.assistNodeIsSuperType = ref.isSuperType(); this.assistNodeIsExtendedType = assistNodeIsExtendedType(astNode, astNodeParent); this.assistNodeIsInterfaceExcludingAnnotation = assistNodeIsInterfaceExcludingAnnotation(astNode, astNodeParent); - + this.assistNodeIsInsideCase = assistNodeIsInsideCase(astNode, astNodeParent); + this.completionToken = ref.completionIdentifier; long completionPosition = ref.sourcePositions[ref.tokens.length]; @@ -3120,6 +3138,7 @@ CompletionOnSingleNameReference singleNameReference = (CompletionOnSingleNameReference) astNode; this.completionToken = singleNameReference.token; SwitchStatement switchStatement = astNodeParent instanceof SwitchStatement ? (SwitchStatement) astNodeParent : null; + this.assistNodeIsInsideCase = assistNodeIsInsideCase(astNode, astNodeParent); if (switchStatement != null && switchStatement.expression.resolvedType != null && switchStatement.expression.resolvedType.isEnum()) { @@ -3195,7 +3214,8 @@ this.assistNodeIsSuperType = singleRef.isSuperType(); this.assistNodeIsExtendedType = assistNodeIsExtendedType(astNode, astNodeParent); this.assistNodeIsInterfaceExcludingAnnotation = assistNodeIsInterfaceExcludingAnnotation(astNode, astNodeParent); - + this.assistNodeIsInsideCase = assistNodeIsInsideCase(astNode, astNodeParent); + // can be the start of a qualified type name if (qualifiedBinding == null) { if (this.completionToken.length == 0 && @@ -4105,6 +4125,13 @@ } return 0; } + + private int computeRelevanceForFinal(boolean onlyFinal, boolean isFinal) { + if (onlyFinal && isFinal) { + return R_FINAL; + } + return 0; + } private long computeTargetedElement(CompletionOnAnnotationOfType fakeNode) { ASTNode annotatedElement = fakeNode.potentialAnnotatedNode; @@ -5968,6 +5995,11 @@ if (this.options.checkVisibility && !field.canBeSeenBy(receiverType, invocationSite, scope)) continue next; + // don't propose array types in case expression + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=195346 + if (this.assistNodeIsInsideCase && field.type instanceof ArrayBinding) + continue next; + int ptr = this.uninterestingBindingsPtr; // Cases where the binding is uninteresting eg. for completion occurring inside a field declaration, // the field binding is uninteresting and shouldn't be proposed. @@ -6064,6 +6096,7 @@ relevance += computeRelevanceForExpectingType(field.type); relevance += computeRelevanceForEnumConstant(field.type); relevance += computeRelevanceForStatic(onlyStaticFields, field.isStatic()); + relevance += computeRelevanceForFinal(this.assistNodeIsInsideCase, field.isFinal()); relevance += computeRelevanceForQualification(prefixRequired); relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); if (onlyStaticFields && this.insideQualifiedReference) { @@ -11353,6 +11386,11 @@ if (local.isSecret()) continue next; + + // don't propose array types in case expression + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=195346 + if (this.assistNodeIsInsideCase && local.type instanceof ArrayBinding) + continue next; int ptr = this.uninterestingBindingsPtr; // Cases where the binding is uninteresting eg. for completion occurring inside a local var @@ -11380,6 +11418,7 @@ relevance += computeRelevanceForEnumConstant(local.type); relevance += computeRelevanceForQualification(false); relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for local variable + relevance += computeRelevanceForFinal(this.assistNodeIsInsideCase, local.isFinal()); this.noProposal = false; if(!this.requestor.isIgnored(CompletionProposal.LOCAL_VARIABLE_REF)) { InternalCompletionProposal proposal = createProposal(CompletionProposal.LOCAL_VARIABLE_REF, this.actualCompletionPosition); Index: codeassist/org/eclipse/jdt/internal/codeassist/RelevanceConstants.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/RelevanceConstants.java,v retrieving revision 1.37 diff -u -r1.37 RelevanceConstants.java --- codeassist/org/eclipse/jdt/internal/codeassist/RelevanceConstants.java 9 Jul 2009 10:47:41 -0000 1.37 +++ codeassist/org/eclipse/jdt/internal/codeassist/RelevanceConstants.java 21 Jun 2010 12:02:18 -0000 @@ -53,4 +53,5 @@ int R_NO_PROBLEMS = 1; int R_RESOLVED = 1; int R_TARGET = 5; + int R_FINAL = 3; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=195346 } #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.220 diff -u -r1.220 CompletionTests.java --- src/org/eclipse/jdt/core/tests/model/CompletionTests.java 21 Jun 2010 07:13:29 -0000 1.220 +++ src/org/eclipse/jdt/core/tests/model/CompletionTests.java 21 Jun 2010 12:03:55 -0000 @@ -1897,7 +1897,7 @@ this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner); assertResults( - "zzz[FIELD_REF]{zzz, LCompletionAfterCase1;, I, zzz, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_EXACT_EXPECTED_TYPE + R_CASE + R_UNQUALIFIED+ R_NON_RESTRICTED) + "}", + "zzz[FIELD_REF]{zzz, LCompletionAfterCase1;, I, zzz, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_EXACT_EXPECTED_TYPE + R_CASE + R_UNQUALIFIED + R_NON_RESTRICTED + R_FINAL) + "}", requestor.getResults()); } public void testCompletionAfterCase2() throws JavaModelException { @@ -1921,7 +1921,7 @@ this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner); assertResults( - "zzz[FIELD_REF]{zzz, LCompletionAfterCase2;, I, zzz, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_EXACT_EXPECTED_TYPE + R_CASE + R_UNQUALIFIED+ R_NON_RESTRICTED) + "}", + "zzz[FIELD_REF]{zzz, LCompletionAfterCase2;, I, zzz, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_EXACT_EXPECTED_TYPE + R_CASE + R_UNQUALIFIED + R_NON_RESTRICTED + R_FINAL) + "}", requestor.getResults()); } //https://bugs.eclipse.org/bugs/show_bug.cgi?id=111882 @@ -1952,13 +1952,11 @@ this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner); assertResults( - "ZZZ2[FIELD_REF]{ZZZ2, Ltest.CompletionAfterCase2;, J, ZZZ2, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_UNQUALIFIED+ R_NON_RESTRICTED) + "}\n" + - "ZZZ3[FIELD_REF]{ZZZ3, Ltest.CompletionAfterCase2;, D, ZZZ3, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_UNQUALIFIED+ R_NON_RESTRICTED) + "}\n" + - "ZZZ4[FIELD_REF]{ZZZ4, Ltest.CompletionAfterCase2;, Ljava.lang.Object;, ZZZ4, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_UNQUALIFIED+ R_NON_RESTRICTED) + "}\n" + - "ZZZ5[FIELD_REF]{ZZZ5, Ltest.CompletionAfterCase2;, [I, ZZZ5, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_UNQUALIFIED+ R_NON_RESTRICTED) + "}\n" + - "ZZZ6[FIELD_REF]{ZZZ6, Ltest.CompletionAfterCase2;, [Ljava.lang.Object;, ZZZ6, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_UNQUALIFIED+ R_NON_RESTRICTED) + "}\n" + - "ZZZ7[FIELD_REF]{ZZZ7, Ltest.CompletionAfterCase2;, S, ZZZ7, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_EXPECTED_TYPE + R_CASE + R_UNQUALIFIED+ R_NON_RESTRICTED) + "}\n" + - "ZZZ1[FIELD_REF]{ZZZ1, Ltest.CompletionAfterCase2;, I, ZZZ1, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_EXACT_EXPECTED_TYPE + R_CASE + R_UNQUALIFIED+ R_NON_RESTRICTED) + "}", + "ZZZ2[FIELD_REF]{ZZZ2, Ltest.CompletionAfterCase2;, J, ZZZ2, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_UNQUALIFIED + R_NON_RESTRICTED + R_FINAL) + "}\n" + + "ZZZ3[FIELD_REF]{ZZZ3, Ltest.CompletionAfterCase2;, D, ZZZ3, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_UNQUALIFIED + R_NON_RESTRICTED + R_FINAL) + "}\n" + + "ZZZ4[FIELD_REF]{ZZZ4, Ltest.CompletionAfterCase2;, Ljava.lang.Object;, ZZZ4, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_UNQUALIFIED + R_NON_RESTRICTED + R_FINAL) + "}\n" + + "ZZZ7[FIELD_REF]{ZZZ7, Ltest.CompletionAfterCase2;, S, ZZZ7, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_EXPECTED_TYPE + R_CASE + R_UNQUALIFIED + R_NON_RESTRICTED + R_FINAL) + "}\n" + + "ZZZ1[FIELD_REF]{ZZZ1, Ltest.CompletionAfterCase2;, I, ZZZ1, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_EXACT_EXPECTED_TYPE + R_CASE + R_UNQUALIFIED + R_NON_RESTRICTED + R_FINAL) + "}", requestor.getResults()); } //https://bugs.eclipse.org/bugs/show_bug.cgi?id=111882 @@ -1995,13 +1993,11 @@ this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner); assertResults( - "ZZZ2[FIELD_REF]{ZZZ2, Ltest.TestConstants;, J, ZZZ2, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_QUALIFIED+ R_NON_RESTRICTED) + "}\n" + - "ZZZ3[FIELD_REF]{ZZZ3, Ltest.TestConstants;, D, ZZZ3, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_QUALIFIED+ R_NON_RESTRICTED) + "}\n" + - "ZZZ4[FIELD_REF]{ZZZ4, Ltest.TestConstants;, Ljava.lang.Object;, ZZZ4, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_QUALIFIED+ R_NON_RESTRICTED) + "}\n" + - "ZZZ5[FIELD_REF]{ZZZ5, Ltest.TestConstants;, [I, ZZZ5, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_QUALIFIED+ R_NON_RESTRICTED) + "}\n" + - "ZZZ6[FIELD_REF]{ZZZ6, Ltest.TestConstants;, [Ljava.lang.Object;, ZZZ6, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_QUALIFIED+ R_NON_RESTRICTED) + "}\n" + - "ZZZ7[FIELD_REF]{ZZZ7, Ltest.TestConstants;, S, ZZZ7, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_EXPECTED_TYPE + R_CASE + R_QUALIFIED+ R_NON_RESTRICTED) + "}\n" + - "ZZZ1[FIELD_REF]{ZZZ1, Ltest.TestConstants;, I, ZZZ1, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_EXACT_EXPECTED_TYPE + R_CASE + R_QUALIFIED+ R_NON_RESTRICTED) + "}", + "ZZZ2[FIELD_REF]{ZZZ2, Ltest.TestConstants;, J, ZZZ2, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_QUALIFIED + R_NON_RESTRICTED + R_FINAL) + "}\n" + + "ZZZ3[FIELD_REF]{ZZZ3, Ltest.TestConstants;, D, ZZZ3, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_QUALIFIED + R_NON_RESTRICTED + R_FINAL) + "}\n" + + "ZZZ4[FIELD_REF]{ZZZ4, Ltest.TestConstants;, Ljava.lang.Object;, ZZZ4, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_QUALIFIED + R_NON_RESTRICTED + R_FINAL) + "}\n" + + "ZZZ7[FIELD_REF]{ZZZ7, Ltest.TestConstants;, S, ZZZ7, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_EXPECTED_TYPE + R_CASE + R_QUALIFIED + R_NON_RESTRICTED + R_FINAL) + "}\n" + + "ZZZ1[FIELD_REF]{ZZZ1, Ltest.TestConstants;, I, ZZZ1, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_EXACT_EXPECTED_TYPE + R_CASE + R_QUALIFIED + R_NON_RESTRICTED + R_FINAL) + "}", requestor.getResults()); } //https://bugs.eclipse.org/bugs/show_bug.cgi?id=222080 @@ -21378,4 +21374,84 @@ "myVar1[LOCAL_VARIABLE_REF]{myVar1, null, I, myVar1, null, 57}", requestor.getResults()); } + +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=195346 +// To verify that array types aren't proposed inside case, and also +// that finals have a higher priority in suggestions inside case expressions. +public void testBug195346a() throws JavaModelException { + this.workingCopies = new ICompilationUnit[1]; + this.workingCopies[0] = getWorkingCopy( + "/Completion/src/test/CompletionAfterCase2.java", + "package test;\n" + + "public class CompletionAfterCase2 {\n" + + " static char[] AN_ARRAY = new char[10];\n" + + " static int AN_INT_VALUE = 0;\n" + + " static final int AN_INT_VALUE2 = 0;\n" + + " static final char[] AN_ARRAY2 = {'a','b'};\n" + + " static final int[] AN_INT_ARRAY = null;\n" + + " static final Object[] ANOTHER_ARRAY = null;\n" + + " void foo(int i, final int [] AN_ARRAY_PARAM){\n" + + " final int AN_INT_VAR = 1;\n" + + " final int[] AN_ARRAY_VAR = {1};\n" + + " int AN_INT_VAR2 = 1;\n" + + " switch(i) {\n" + + " case AN\n" + + " }\n" + + " }\n" + + "}\n"); + + CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + String str = this.workingCopies[0].getSource(); + String completeBehind = "AN"; + int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); + this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner); + + assertResults( + "AN_INT_VALUE[FIELD_REF]{AN_INT_VALUE, Ltest.CompletionAfterCase2;, I, AN_INT_VALUE, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_UNQUALIFIED + R_NON_RESTRICTED + R_EXACT_EXPECTED_TYPE) + "}\n" + + "AN_INT_VAR2[LOCAL_VARIABLE_REF]{AN_INT_VAR2, null, I, AN_INT_VAR2, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_UNQUALIFIED + R_NON_RESTRICTED + R_EXACT_EXPECTED_TYPE) + "}\n" + + "AN_INT_VALUE2[FIELD_REF]{AN_INT_VALUE2, Ltest.CompletionAfterCase2;, I, AN_INT_VALUE2, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_UNQUALIFIED + R_NON_RESTRICTED + R_EXACT_EXPECTED_TYPE + R_FINAL) + "}\n" + + "AN_INT_VAR[LOCAL_VARIABLE_REF]{AN_INT_VAR, null, I, AN_INT_VAR, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_UNQUALIFIED + R_NON_RESTRICTED + R_EXACT_EXPECTED_TYPE + R_FINAL) + "}", + requestor.getResults()); +} + +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=195346 +// To verify that array types aren't proposed inside case, and also +// that finals have a higher priority in suggestions inside case expressions. +public void testBug195346b() throws JavaModelException { + this.workingCopies = new ICompilationUnit[1]; + this.workingCopies[0] = getWorkingCopy( + "/Completion/src/test/CompletionAfterCase2.java", + "package test;\n" + + "public class CompletionAfterCase2 {\n" + + " class AN_INNER_CLASS {\n" + + " static final int abc = 1;\n" + + " }\n" + + " static char[] AN_ARRAY = new char[10];\n" + + " static int AN_INT_VALUE = 0;\n" + + " static final int AN_INT_VALUE2 = 0;\n" + + " static final char[] AN_ARRAY2 = {'a','b'};\n" + + " static final int[] AN_INT_ARRAY = null;\n" + + " static final Object[] ANOTHER_ARRAY = null;\n" + + " void foo(int i, final int [] AN_ARRAY_PARAM){\n" + + " final int AN_INT_VAR = 1;\n" + + " final int[] AN_ARRAY_VAR = {1};\n" + + " int AN_INT_VAR2 = 1;\n" + + " switch(i) {\n" + + " case CompletionAfterCase2.AN\n" + + " }\n" + + " }\n" + + "}\n"); + + CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + String str = this.workingCopies[0].getSource(); + String completeBehind = "AN"; + int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); + this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner); + + assertResults( + "CompletionAfterCase2.AN_INNER_CLASS[TYPE_REF]{AN_INNER_CLASS, test, Ltest.CompletionAfterCase2$AN_INNER_CLASS;, null, null, " + (R_DEFAULT + R_INTERESTING + R_CASE + R_UNQUALIFIED + R_NON_RESTRICTED) + "}\n" + + "AN_INT_VALUE[FIELD_REF]{AN_INT_VALUE, Ltest.CompletionAfterCase2;, I, AN_INT_VALUE, null, " + (R_DEFAULT + R_INTERESTING + R_CASE + R_UNQUALIFIED + R_NON_RESTRICTED + R_EXACT_EXPECTED_TYPE) + "}\n" + + "AN_INT_VALUE2[FIELD_REF]{AN_INT_VALUE2, Ltest.CompletionAfterCase2;, I, AN_INT_VALUE2, null, " + (R_DEFAULT + R_INTERESTING + R_CASE + R_UNQUALIFIED + R_NON_RESTRICTED + R_EXACT_EXPECTED_TYPE + R_FINAL) + "}", + requestor.getResults()); +} }