### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core 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.32 diff -u -r1.32 RelevanceConstants.java --- codeassist/org/eclipse/jdt/internal/codeassist/RelevanceConstants.java 6 Mar 2007 02:38:51 -0000 1.32 +++ codeassist/org/eclipse/jdt/internal/codeassist/RelevanceConstants.java 15 Mar 2007 16:06:06 -0000 @@ -42,4 +42,5 @@ int R_NON_INHERITED = 2; int R_NO_PROBLEMS = 1; int R_RESOLVED = 1; + int R_CONSTRUCTOR = 5; } 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.322 diff -u -r1.322 CompletionEngine.java --- codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java 12 Mar 2007 09:42:26 -0000 1.322 +++ codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java 15 Mar 2007 16:06:06 -0000 @@ -955,6 +955,10 @@ typesFound); } findTypesAndPackages(this.completionToken, scope, typesFound); + if (this.assistNodeIsConstructor && + !this.requestor.isIgnored(CompletionProposal.METHOD_REF)) { + findExactConstructors(this.completionToken, scope, FakeInvocationSite); + } } } else if (!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { findMemberTypes( @@ -1257,6 +1261,7 @@ argTypes, scope, constructorCall, + false, false); } } else if (astNode instanceof CompletionOnQualifiedAllocationExpression) { @@ -1275,6 +1280,7 @@ argTypes, scope, allocExpression, + false, false); } if (!this.requestor.isIgnored(CompletionProposal.ANONYMOUS_CLASS_DECLARATION) @@ -1617,7 +1623,7 @@ if (this.completionToken == null || CharOperation.prefixEquals(this.completionToken, refBinding.sourceName) || (this.options.camelCaseMatch && CharOperation.camelCaseMatch(this.completionToken, refBinding.sourceName))) { - findConstructors(refBinding, null, scope, fieldRef, false); + findConstructors(refBinding, null, scope, fieldRef, false, false); } } } @@ -1683,7 +1689,7 @@ ReferenceBinding ref = (ReferenceBinding) qualifiedBinding; if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF) && ref.isClass()) { - findConstructors(ref, argTypes, scope, allocExpression, false); + findConstructors(ref, argTypes, scope, allocExpression, false, false); } } else if (astNode instanceof CompletionOnJavadocParamNameReference) { if (!this.requestor.isIgnored(CompletionProposal.JAVADOC_PARAM_REF)) { @@ -2186,7 +2192,8 @@ argTypes, scope, invocationSite, - true); + true, + false); } } @@ -2309,6 +2316,315 @@ } } + private void findExactConstructors(char[] token, Scope scope, InvocationSite invocationSite) { + ObjectVector typesFound = new ObjectVector(); + + if (token == null || token.length == 0) + return; + + if (scope.enclosingSourceType() != null) { + findExactNestedTypesConstructors( + token, + scope.enclosingSourceType(), + scope, + invocationSite, + typesFound); + } + + if (this.unitScope != null) { + ReferenceBinding outerInvocationType = scope.enclosingSourceType(); + if(outerInvocationType != null) { + ReferenceBinding temp = outerInvocationType.enclosingType(); + while(temp != null) { + outerInvocationType = temp; + temp = temp.enclosingType(); + } + } + + int typeLength = token.length; + SourceTypeBinding[] types = this.unitScope.topLevelTypes; + + next : for (int i = 0, length = types.length; i < length; i++) { + SourceTypeBinding sourceType = types[i]; + + if (isForbidden(sourceType)) continue next; + + if (sourceType.sourceName == CompletionParser.FAKE_TYPE_NAME) continue next; + if (sourceType.sourceName == TypeConstants.PACKAGE_INFO_NAME) continue next; + + if (typeLength != sourceType.sourceName.length) continue next; + + if (!CharOperation.equals(token, sourceType.sourceName)) continue next; + + for (int j = typesFound.size; --j >= 0;) { + ReferenceBinding otherType = (ReferenceBinding) typesFound.elementAt(j); + + if (sourceType == otherType) continue next; + } + + typesFound.add(sourceType); + + findConstructors( + sourceType, + null, + scope, + invocationSite, + false, + true); + } + } + + SingleTypeReference convertedType = new SingleTypeReference(token, 0); + + this.problemFactory.startCheckingProblems(); + TypeBinding guessedType = null; + switch (scope.kind) { + case Scope.METHOD_SCOPE : + case Scope.BLOCK_SCOPE : + guessedType = convertedType.resolveType((BlockScope)scope); + break; + case Scope.CLASS_SCOPE : + guessedType = convertedType.resolveType((ClassScope)scope); + break; + } + this.problemFactory.stopCheckingProblems(); + if (!this.problemFactory.hasForbiddenProblems && + guessedType instanceof ReferenceBinding && + !guessedType.isTypeVariable()) { + + TypeBinding erasure = guessedType.erasure(); + boolean alreadyFound = false; + for (int j = typesFound.size; --j >= 0;) { + ReferenceBinding otherType = (ReferenceBinding) typesFound.elementAt(j); + + if (erasure == otherType) { + alreadyFound = true; + } + } + if (!alreadyFound) { + typesFound.add(erasure); + + findConstructors( + (ReferenceBinding)erasure, + null, + scope, + invocationSite, + false, + true); + } + } + } + + private void findExactMemberTypesConstructors( + char[] typeName, + ReferenceBinding[] memberTypes, + ReferenceBinding receiverType, + SourceTypeBinding invocationType, + Scope scope, + InvocationSite invocationSite, + ObjectVector typesFound) { + + // Inherited member types which are hidden by subclasses are filtered out + // No visibility checks can be performed without the scope & invocationSite + int typeLength = typeName.length; + next : for (int m = memberTypes.length; --m >= 0;) { + ReferenceBinding memberType = memberTypes[m]; + + if (isForbidden(memberType)) continue next; + + if (typeLength != memberType.sourceName.length) + continue next; + + if (!CharOperation.equals(typeName, memberType.sourceName)) + continue next; + + for (int j = typesFound.size; --j >= 0;) { + ReferenceBinding otherType = (ReferenceBinding) typesFound.elementAt(j); + + if (memberType == otherType) continue next; + } + + typesFound.add(memberType); + + findConstructors( + memberType, + null, + scope, + invocationSite, + false, + true); + } + } + + private void findExactMemberTypesContructors( + char[] typeName, + ReferenceBinding receiverType, + Scope scope, + SourceTypeBinding typeInvocation, + SourceTypeBinding typeToIgnore, + InvocationSite invocationSite, + ObjectVector typesFound) { + + ReferenceBinding currentType = receiverType; + if (typeName == null) + return; + + if (currentType.superInterfaces() == null) return; + + if (this.insideQualifiedReference) { // do not search up the hierarchy + + findExactMemberTypesConstructors( + typeName, + currentType.memberTypes(), + receiverType, + typeInvocation, + scope, + invocationSite, + typesFound); + return; + } + + ReferenceBinding[] interfacesToVisit = null; + int nextPosition = 0; + + do { + ReferenceBinding[] itsInterfaces = currentType.superInterfaces(); + if (itsInterfaces != Binding.NO_SUPERINTERFACES) { + if (interfacesToVisit == null) { + interfacesToVisit = itsInterfaces; + nextPosition = interfacesToVisit.length; + } else { + int itsLength = itsInterfaces.length; + if (nextPosition + itsLength >= interfacesToVisit.length) + System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); + nextInterface : for (int a = 0; a < itsLength; a++) { + ReferenceBinding next = itsInterfaces[a]; + for (int b = 0; b < nextPosition; b++) + if (next == interfacesToVisit[b]) continue nextInterface; + interfacesToVisit[nextPosition++] = next; + } + } + } + + findExactMemberTypesConstructors( + typeName, + currentType.memberTypes(), + receiverType, + typeInvocation, + scope, + invocationSite, + typesFound); + + currentType = currentType.superclass(); + } while (currentType != null); + + if (interfacesToVisit != null) { + for (int i = 0; i < nextPosition; i++) { + ReferenceBinding anInterface = interfacesToVisit[i]; + findExactMemberTypesConstructors( + typeName, + anInterface.memberTypes(), + receiverType, + typeInvocation, + scope, + invocationSite, + typesFound); + + ReferenceBinding[] itsInterfaces = anInterface.superInterfaces(); + if (itsInterfaces != Binding.NO_SUPERINTERFACES) { + int itsLength = itsInterfaces.length; + if (nextPosition + itsLength >= interfacesToVisit.length) + System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); + nextInterface : for (int a = 0; a < itsLength; a++) { + ReferenceBinding next = itsInterfaces[a]; + for (int b = 0; b < nextPosition; b++) + if (next == interfacesToVisit[b]) continue nextInterface; + interfacesToVisit[nextPosition++] = next; + } + } + } + } + } + + private void findExactNestedTypesConstructors( + char[] typeName, + SourceTypeBinding currentType, + Scope scope, + InvocationSite invocationSite, + ObjectVector typesFound) { + + if (typeName == null) + return; + + int typeLength = typeName.length; + + SourceTypeBinding nextTypeToIgnore = null; + while (scope != null) { // done when a COMPILATION_UNIT_SCOPE is found + + switch (scope.kind) { + + case Scope.METHOD_SCOPE : + case Scope.BLOCK_SCOPE : + BlockScope blockScope = (BlockScope) scope; + + next : for (int i = 0, length = blockScope.subscopeCount; i < length; i++) { + + if (blockScope.subscopes[i] instanceof ClassScope) { + SourceTypeBinding localType = + ((ClassScope) blockScope.subscopes[i]).referenceContext.binding; + + if (!localType.isAnonymousType()) { + if (this.isForbidden(localType)) + continue next; + + if (typeLength != localType.sourceName.length) + continue next; + + if (!CharOperation.equals(typeName, localType.sourceName)) + continue next; + + for (int j = typesFound.size; --j >= 0;) { + ReferenceBinding otherType = (ReferenceBinding) typesFound.elementAt(j); + + if (localType == otherType) continue next; + } + + typesFound.add(localType); + + findConstructors( + localType, + null, + scope, + invocationSite, + false, + true); + } + } + } + break; + + case Scope.CLASS_SCOPE : + SourceTypeBinding enclosingSourceType = scope.enclosingSourceType(); + findExactMemberTypesContructors( + typeName, + enclosingSourceType, + scope, + currentType, + nextTypeToIgnore, + invocationSite, + typesFound); + nextTypeToIgnore = enclosingSourceType; + if (typeLength == 0) + return; // do not search outside the class scope if no prefix was provided + break; + + case Scope.COMPILATION_UNIT_SCOPE : + return; + } + scope = scope.parent; + } + } + private void findExceptionFromTryStatement( char[] typeName, ReferenceBinding exceptionType, @@ -2586,7 +2902,10 @@ TypeBinding[] argTypes, Scope scope, InvocationSite invocationSite, - boolean forAnonymousType) { + boolean forAnonymousType, + boolean forExactConstructors) { + + char[] simpleTypename = currentType.sourceName; // No visibility checks can be performed without the scope & invocationSite MethodBinding[] methods = currentType.availableMethods(); @@ -2662,6 +2981,52 @@ this.printDebug(proposal); } } + } else if (forExactConstructors) { + if (this.source != null + && this.source.length > this.endPosition + && this.source[this.endPosition] == '(') { + completion = simpleTypename; + } else { + completion = CharOperation.concat(simpleTypename, new char[] { '(', ')' }); + } + + int relevance = computeBaseRelevance(); + relevance += computeRelevanceForResolution(); + relevance += computeRelevanceForInterestingProposal(); + relevance += computeRelevanceForCaseMatching(simpleTypename, simpleTypename); + relevance += computeRelevanceForExpectingType(currentType); + relevance += computeRelevanceForQualification(false); + relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for type in the current unit + relevance += R_CONSTRUCTOR; + + // Create standard proposal + this.noProposal = false; + if(!this.requestor.isIgnored(CompletionProposal.METHOD_REF) && (this.assistNodeInJavadoc & CompletionOnJavadoc.ONLY_INLINE_TAG) == 0) { + CompletionProposal proposal = this.createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition); + proposal.setDeclarationSignature(getSignature(currentType)); + proposal.setSignature(getSignature(constructor)); + MethodBinding original = constructor.original(); + if(original != constructor) { + proposal.setOriginalSignature(getSignature(original)); + } + proposal.setDeclarationPackageName(currentType.qualifiedPackageName()); + proposal.setDeclarationTypeName(currentType.qualifiedSourceName()); + proposal.setParameterPackageNames(parameterPackageNames); + proposal.setParameterTypeNames(parameterTypeNames); + //proposal.setPackageName(null); + //proposal.setTypeName(null); + proposal.setName(currentType.sourceName()); + proposal.setIsContructor(true); + proposal.setCompletion(completion); + proposal.setFlags(constructor.modifiers); + proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); + proposal.setRelevance(relevance); + if(parameterNames != null) proposal.setParameterNames(parameterNames); + this.requestor.accept(proposal); + if(DEBUG) { + this.printDebug(proposal); + } + } } else { int relevance = computeBaseRelevance(); relevance += computeRelevanceForResolution();