### 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.411 diff -u -r1.411 CompletionEngine.java --- codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java 22 Apr 2010 16:11:44 -0000 1.411 +++ codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java 1 Jun 2010 18:32:25 -0000 @@ -522,6 +522,8 @@ boolean assistNodeIsExtendedType; int assistNodeInJavadoc = 0; boolean assistNodeCanBeSingleMemberAnnotation = false; + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=195346 + boolean assistNodeIsInsideCase = false; long targetedElement; @@ -1691,6 +1693,21 @@ return true; } + 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; i < ((SwitchStatement) astNodeParent).caseCount; i++) { + CompletionNodeDetector detector = new CompletionNodeDetector(astNode, cases[i]); + if (detector.containsCompletionNode()) { + return true; + } + } + } + return false; + } + /** * Ask the engine to compute a completion at the specified position * of the given compilation unit. @@ -2898,7 +2915,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); // complete field members with missing fields type @@ -3041,7 +3058,7 @@ this.assistNodeIsConstructor = ref.isConstructorType; this.assistNodeIsSuperType = ref.isSuperType(); this.assistNodeIsExtendedType = assistNodeIsExtendedType(astNode, astNodeParent); - + this.assistNodeIsInsideCase = assistNodeIsInsideCase(astNode, astNodeParent); this.completionToken = ref.completionIdentifier; long completionPosition = ref.sourcePositions[ref.tokens.length]; @@ -3101,6 +3118,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()) { @@ -3175,7 +3193,8 @@ this.assistNodeIsConstructor = singleRef.isConstructorType; this.assistNodeIsSuperType = singleRef.isSuperType(); this.assistNodeIsExtendedType = assistNodeIsExtendedType(astNode, astNodeParent); - + this.assistNodeIsInsideCase = assistNodeIsInsideCase(astNode, astNodeParent); + // can be the start of a qualified type name if (qualifiedBinding == null) { if (this.completionToken.length == 0 && @@ -4086,6 +4105,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; @@ -5947,7 +5973,12 @@ 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; + boolean prefixRequired = false; for (int i = fieldsFound.size; --i >= 0;) { @@ -6034,6 +6065,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) { @@ -11312,7 +11344,12 @@ 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; + for (int f = 0; f < localsFound.size; f++) { LocalVariableBinding otherLocal = (LocalVariableBinding) localsFound.elementAt(f); @@ -11329,6 +11366,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 1 Jun 2010 18:32:25 -0000 @@ -53,4 +53,6 @@ int R_NO_PROBLEMS = 1; int R_RESOLVED = 1; int R_TARGET = 5; + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=195346 + int R_FINAL = 3; } #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.219 diff -u -r1.219 CompletionTests.java --- src/org/eclipse/jdt/core/tests/model/CompletionTests.java 22 Apr 2010 16:12:50 -0000 1.219 +++ src/org/eclipse/jdt/core/tests/model/CompletionTests.java 1 Jun 2010 18:32:40 -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 @@ -21333,4 +21329,84 @@ "toString[METHOD_REF]{toString(), Ljava.lang.Object;, ()Ljava.lang.String;, null, null, toString, null, replace[" + start1 + ", " + end1 + "], token[" + start1 + ", " + end1 +"], " + relevance1 + "}", 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()); +} }