Index: plugin.xml =================================================================== RCS file: /home/eclipse/org.eclipse.jdt.core/plugin.xml,v retrieving revision 1.78.2.2 diff -u -r1.78.2.2 plugin.xml --- plugin.xml 3 Jun 2005 08:25:53 -0000 1.78.2.2 +++ plugin.xml 2 Aug 2005 01:43:13 -0000 @@ -46,6 +46,14 @@ + + + + + + Index: META-INF/MANIFEST.MF =================================================================== RCS file: /home/eclipse/org.eclipse.jdt.core/META-INF/MANIFEST.MF,v retrieving revision 1.10.2.1 diff -u -r1.10.2.1 MANIFEST.MF --- META-INF/MANIFEST.MF 3 Jun 2005 08:25:55 -0000 1.10.2.1 +++ META-INF/MANIFEST.MF 2 Aug 2005 01:43:13 -0000 @@ -10,6 +10,7 @@ Bundle-Localization: plugin Export-Package: org.eclipse.jdt.core, org.eclipse.jdt.core.compiler, + org.eclipse.jdt.core.completion, org.eclipse.jdt.core.dom, org.eclipse.jdt.core.dom.rewrite, org.eclipse.jdt.core.eval, Index: codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java =================================================================== RCS file: /home/eclipse/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java,v retrieving revision 1.219.2.2 diff -u -r1.219.2.2 CompletionEngine.java --- codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java 1 Jul 2005 17:57:50 -0000 1.219.2.2 +++ codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java 2 Aug 2005 01:43:14 -0000 @@ -10,6 +10,8 @@ *******************************************************************************/ package org.eclipse.jdt.internal.codeassist; +import java.util.ArrayList; +import java.util.List; import java.util.Locale; import java.util.Map; @@ -21,11 +23,12 @@ import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.IType; +import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.Signature; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.core.compiler.IProblem; - +import org.eclipse.jdt.core.completion.ICompletionParticipant; import org.eclipse.jdt.internal.codeassist.complete.*; import org.eclipse.jdt.internal.codeassist.impl.AssistParser; import org.eclipse.jdt.internal.codeassist.impl.Engine; @@ -124,6 +127,7 @@ HashtableOfObject knownPkgs = new HashtableOfObject(10); HashtableOfObject knownTypes = new HashtableOfObject(10); Scanner nameScanner; + JavaCompletionEvent completionEvent = null; /* static final char[][] mainDeclarations = @@ -415,7 +419,7 @@ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); proposal.setRelevance(relevance); proposal.setAccessibility(accessibility); - this.requestor.accept(proposal); + this.acceptProposal(proposal); if(DEBUG) { this.printDebug(proposal); } @@ -587,7 +591,7 @@ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); proposal.setRelevance(relevance); proposal.setAccessibility(accessibility); - this.requestor.accept(proposal); + this.acceptProposal(proposal); if(DEBUG) { this.printDebug(proposal); } @@ -626,7 +630,7 @@ : packageName); proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); proposal.setRelevance(relevance); - this.requestor.accept(proposal); + acceptProposal(proposal); if(DEBUG) { this.printDebug(proposal); } @@ -844,7 +848,7 @@ proposal.setCompletion(Keywords.THIS); proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); proposal.setRelevance(relevance); - this.requestor.accept(proposal); + acceptProposal(proposal); if(DEBUG) { this.printDebug(proposal); } @@ -1528,9 +1532,41 @@ System.out.print("COMPLETION - Parent Node : "); //$NON-NLS-1$ System.out.println(this.parser.assistNodeParent); } - } + } + final List icps = JavaCore.getCompletionParticipants(javaProject); + List actualParticipants = null; + if( icps != null && !icps.isEmpty() ){ + actualParticipants = new ArrayList(icps.size()); + final int currentEventMask = getCurrentCompletionMask(); + for( int i=0, size=icps.size(); i 0) ) + actualParticipants.add(icp); + } + // only going to build out the infra-structure if there are actually + // participants that are interested in the event. + if( !actualParticipants.isEmpty() ){ + completionEvent = JavaCompletionEvent.createCompletionEvent( + parsedUnit, sourceUnit, e.astNode, compilerOptions, source, + actualCompletionPosition, javaProject, requestor); + requestParticipantFilter(actualParticipants, completionEvent); + } + } // if null then we found a problem in the completion node contextAccepted = complete(e.astNode, this.parser.assistNodeParent, e.qualifiedBinding, e.scope, e.insideTypeAnnotation); + if( completionEvent != null ){ + try{ + for( int i=0, size=actualParticipants.size(); i end ) + end = memberValuePairs[i].sourceEnd; + } + } + if( completedMemberValuePair != null && completedMemberValuePair.sourceEnd > end ) + end = completedMemberValuePair.sourceEnd; + this.declarationSourceEnd = end; + this.sourceEnd = end; } - + public TypeBinding resolveType(BlockScope scope) { super.resolveType(scope); Index: codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java =================================================================== RCS file: /home/eclipse/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java,v retrieving revision 1.126.2.2 diff -u -r1.126.2.2 CompletionParser.java --- codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java 1 Jul 2005 17:57:49 -0000 1.126.2.2 +++ codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java 2 Aug 2005 01:43:15 -0000 @@ -75,6 +75,8 @@ public int cursorLocation; public ASTNode assistNodeParent; // the parent node of assist node + private int[] completionElementKindStack = null; + /* the following fields are internal flags */ // block kind @@ -172,6 +174,7 @@ } CompletionOnFieldType fieldDeclaration = new CompletionOnFieldType(fieldType, false); + populateCompletionElementKind(); // retrieve available modifiers if any if (intPtr >= 2 && intStack[intPtr-1] == this.lastModifiersStart && intStack[intPtr-2] == this.lastModifiers){ @@ -193,6 +196,7 @@ if (orphan instanceof TypeReference){ currentElement = currentElement.parent.add( new CompletionOnFieldType((TypeReference)orphan, true), 0); + populateCompletionElementKind(); return; } } @@ -209,6 +213,7 @@ FAKE_TYPE_NAME, this.compilationUnit.compilationResult(), (Annotation)orphan); + populateCompletionElementKind(); currentElement.add(fakeType, 0); return; } @@ -241,6 +246,7 @@ if (expression instanceof SingleNameReference) { SingleNameReference nameReference = (SingleNameReference) expression; CompletionOnMemberValueName memberValueName = new CompletionOnMemberValueName(nameReference.token, nameReference.sourceStart, nameReference.sourceEnd); + populateCompletionElementKind(); buildMoreAnnotationCompletionContext(memberValueName); return; @@ -316,6 +322,7 @@ CompletionNodeDetector detector = new CompletionNodeDetector(this.assistNode, typeParameter); if(detector.containsCompletionNode()) { this.currentElement.add(new CompletionOnMethodTypeParameter(new TypeParameter[]{typeParameter},this.compilationUnit.compilationResult()), 0); + populateCompletionElementKind(); } return; } @@ -355,6 +362,7 @@ if(this.assistNodeParent != null && this.assistNodeParent instanceof TypeReference) { if(this.currentElement instanceof RecoveredType) { this.currentElement = this.currentElement.add(new CompletionOnFieldType((TypeReference)this.assistNodeParent, false), 0); + populateCompletionElementKind(); } else { this.currentElement = this.currentElement.add((TypeReference)this.assistNodeParent, 0); } @@ -451,7 +459,7 @@ this.assistNode = memberValuePair; this.assistNodeParent = annotation; - + populateCompletionElementKind(); if (memberValuePair.sourceEnd >= this.lastCheckPoint) { this.lastCheckPoint = memberValuePair.sourceEnd + 1; } @@ -480,14 +488,29 @@ new NormalAnnotation( typeReference, this.intStack[this.intPtr--]); - annotation.memberValuePairs = memberValuePairs; - + annotation.memberValuePairs = memberValuePairs; + int end = annotation.sourceEnd; + // doing the best possible to fill in the ending offsets. + if( memberValuePairs != null ){ + for( int i=0, len=memberValuePairs.length; i end ) + end = memberValuePairs[i].sourceEnd; + } + } + annotation.sourceEnd = end; + annotation.declarationSourceEnd = end; } TypeDeclaration fakeType = new CompletionOnAnnotationOfType( FAKE_TYPE_NAME, this.compilationUnit.compilationResult(), annotation); + populateCompletionElementKind(); + + fakeType.declarationSourceStart = annotation.sourceStart; + fakeType.declarationSourceEnd = annotation.sourceEnd; + fakeType.bodyStart = annotation.sourceEnd; + fakeType.bodyEnd = annotation.sourceEnd; currentElement.add(fakeType, 0); } @@ -535,6 +558,8 @@ if(invocType != ALLOCATION && invocType != QUALIFIED_ALLOCATION) { MessageSend messageSend = new MessageSend(); + messageSend.sourceStart = expression.sourceStart; + messageSend.sourceEnd = expression.sourceEnd; messageSend.selector = identifierStack[selector]; messageSend.arguments = arguments; @@ -575,7 +600,10 @@ messageSend.receiver = ThisReference.implicitThis(); break; } - assistNodeParent = messageSend; + + if( messageSend.receiver != null ) + messageSend.sourceStart = messageSend.receiver.sourceStart; + assistNodeParent = messageSend; } else { if(invocType == ALLOCATION) { AllocationExpression allocationExpr = new AllocationExpression(); @@ -860,6 +888,7 @@ } if(currentElement instanceof RecoveredType) { currentElement = currentElement.add(new CompletionOnFieldType(ref, false), 0); + populateCompletionElementKind(); } else { currentElement = currentElement.add(ref, 0); } @@ -991,6 +1020,7 @@ this.identifierLengthPtr--; // pop the length that was used to say it is a primitive type this.assistNode = access; this.isOrphanCompletionNode = true; + populateCompletionElementKind(); return true; } @@ -1012,6 +1042,7 @@ access.completionIdentifier = source; this.assistNode = access; this.isOrphanCompletionNode = true; + populateCompletionElementKind(); return true; } @@ -1077,6 +1108,7 @@ this.assistNode = new CompletionOnKeyword2(ident, pos, keywords); this.lastCheckPoint = assistNode.sourceEnd + 1; this.isOrphanCompletionNode = true; + populateCompletionElementKind(); return true; } } @@ -1100,6 +1132,7 @@ Keywords.INSTANCEOF); this.lastCheckPoint = assistNode.sourceEnd + 1; this.isOrphanCompletionNode = true; + populateCompletionElementKind(); return true; } } @@ -1154,6 +1187,7 @@ if (invocType != ALLOCATION && invocType != QUALIFIED_ALLOCATION) { // creates completion on message send CompletionOnMessageSend messageSend = new CompletionOnMessageSend(); + populateCompletionElementKind(); messageSend.arguments = arguments; switch (invocType) { case NO_RECEIVER: @@ -1209,6 +1243,7 @@ CompletionOnExplicitConstructorCall call = new CompletionOnExplicitConstructorCall( (selectorPtr == THIS_CONSTRUCTOR) ? ExplicitConstructorCall.This : ExplicitConstructorCall.Super); call.arguments = arguments; + populateCompletionElementKind(); if (invocType == QUALIFIED_ALLOCATION) { call.qualification = this.expressionStack[qualifierExprPtr]; } @@ -1226,6 +1261,7 @@ // creates an allocation expression CompletionOnQualifiedAllocationExpression allocExpr = new CompletionOnQualifiedAllocationExpression(); allocExpr.arguments = arguments; + populateCompletionElementKind(); if(this.genericsLengthPtr < 0) { pushOnGenericsLengthStack(0); pushOnGenericsIdentifiersLengthStack(identifierLengthStack[identifierLengthPtr]); @@ -1354,6 +1390,7 @@ this.assistNode = memberValueName; this.lastCheckPoint = this.assistNode.sourceEnd + 1; this.isOrphanCompletionNode = true; + populateCompletionElementKind(); return true; } @@ -1436,6 +1473,7 @@ identifierStack[ptr], identifierPositionStack[ptr], keywords); + populateCompletionElementKind(); completionOnKeyword.canCompleteEmptyToken = true; type.superclass = completionOnKeyword; type.superclass.bits |= ASTNode.IsSuperType; @@ -1453,6 +1491,7 @@ type.superInterfaces[0].bits |= ASTNode.IsSuperType; this.assistNode = completionOnKeyword; this.lastCheckPoint = completionOnKeyword.sourceEnd + 1; + populateCompletionElementKind(); } } } @@ -1655,6 +1694,7 @@ type.superclass.bits |= ASTNode.IsSuperType; this.assistNode = type.superclass; this.lastCheckPoint = type.superclass.sourceEnd + 1; + populateCompletionElementKind(); } } } @@ -1779,6 +1819,7 @@ lastCheckPoint = type.sourceEnd + 1; currentElement = currentElement.add(completionFieldDecl, 0); lastIgnoredToken = -1; + populateCompletionElementKind(); } } } @@ -1873,6 +1914,7 @@ namePositions, type, intStack[intPtr + 1] & ~AccDeprecated); // modifiers + populateCompletionElementKind(); // consume annotations int length; if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) { @@ -2019,6 +2061,7 @@ if(scanner.getLineNumber(type.sourceStart) != scanner.getLineNumber((int) (selectorSource >>> 32))) { FieldDeclaration completionFieldDecl = new CompletionOnFieldType(type, false); + populateCompletionElementKind(); // consume annotations int length; if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) { @@ -2036,6 +2079,7 @@ lastIgnoredToken = -1; } else { CompletionOnMethodReturnType md = new CompletionOnMethodReturnType(type, this.compilationUnit.compilationResult); + populateCompletionElementKind(); // consume annotations int length; if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) { @@ -2064,7 +2108,7 @@ } else { // MethodHeaderName ::= Modifiersopt Type 'Identifier' '(' CompletionOnMethodName md = new CompletionOnMethodName(this.compilationUnit.compilationResult); - + populateCompletionElementKind(); //name md.selector = identifierStack[identifierPtr]; long selectorSource = identifierPositionStack[identifierPtr--]; @@ -2142,6 +2186,7 @@ recoveredMethod.foundOpeningBrace = true; this.assistNode = completionOnKeyword; this.lastCheckPoint = completionOnKeyword.sourceEnd + 1; + populateCompletionElementKind(); } } } @@ -2174,6 +2219,7 @@ recoveredMethod.foundOpeningBrace = true; this.assistNode = completionOnKeyword; this.lastCheckPoint = completionOnKeyword.sourceEnd + 1; + populateCompletionElementKind(); } } } @@ -2225,6 +2271,7 @@ this.intPtr--; markerAnnotation.declarationSourceEnd = markerAnnotation.sourceEnd; pushOnExpressionStack(markerAnnotation); + populateCompletionElementKind(); assistNode = markerAnnotation; this.isOrphanCompletionNode = true; @@ -2261,6 +2308,7 @@ this.assistNode = memberValueName; this.lastCheckPoint = this.assistNode.sourceEnd + 1; this.isOrphanCompletionNode = true; + populateCompletionElementKind(); this.restartRecovery = true; } @@ -2851,6 +2899,7 @@ Keywords.EXTENDS); keyword.canCompleteEmptyToken = true; typeParameter.type = keyword; + populateCompletionElementKind(); this.identifierPtr--; this.identifierLengthPtr--; @@ -2899,6 +2948,7 @@ keyword.canCompleteEmptyToken = true; wildcard.kind = Wildcard.EXTENDS; wildcard.bound = keyword; + populateCompletionElementKind(); this.identifierPtr--; this.identifierLengthPtr--; @@ -2958,12 +3008,15 @@ } public ImportReference createAssistImportReference(char[][] tokens, long[] positions, int mod){ + populateCompletionElementKind(); return new CompletionOnImportReference(tokens, positions, mod); } public ImportReference createAssistPackageReference(char[][] tokens, long[] positions){ - return new CompletionOnPackageReference(tokens, positions); + populateCompletionElementKind(); + return new CompletionOnPackageReference(tokens, positions); } public NameReference createQualifiedAssistNameReference(char[][] previousIdentifiers, char[] assistName, long[] positions){ + populateCompletionElementKind(); return new CompletionOnQualifiedNameReference( previousIdentifiers, assistName, @@ -2971,8 +3024,9 @@ isInsideAttributeValue()); } public TypeReference createQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] assistName, long[] positions){ - switch (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER)) { - case K_NEXT_TYPEREF_IS_EXCEPTION : + populateCompletionElementKind(); + switch (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER)) { + case K_NEXT_TYPEREF_IS_EXCEPTION : return new CompletionOnQualifiedExceptionReference(previousIdentifiers, assistName, positions); case K_NEXT_TYPEREF_IS_CLASS : return new CompletionOnQualifiedClassReference(previousIdentifiers, assistName, positions); @@ -2992,6 +3046,7 @@ if(!isParameterized) { return this.createQualifiedAssistTypeReference(previousIdentifiers, assistName, positions); } else { + populateCompletionElementKind(); switch (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER)) { case K_NEXT_TYPEREF_IS_EXCEPTION : return new CompletionOnParameterizedQualifiedTypeReference( @@ -3025,6 +3080,7 @@ } public NameReference createSingleAssistNameReference(char[] assistName, long position) { int kind = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER); + populateCompletionElementKind(); if(!isInsideMethod()) { return new CompletionOnSingleNameReference(assistName, position, isInsideAttributeValue()); } else { @@ -3106,6 +3162,7 @@ } } public TypeReference createSingleAssistTypeReference(char[] assistName, long position) { + populateCompletionElementKind(); switch (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER)) { case K_NEXT_TYPEREF_IS_EXCEPTION : return new CompletionOnExceptionReference(assistName, position) ; @@ -3232,6 +3289,20 @@ } return false; } +/** + * @return true iff assist node is inside an annotation. + */ +public boolean isCompletionInsideAnnotation(){ + if( this.completionElementKindStack == null ) return false; + int i = this.completionElementKindStack.length - 1; + while( i > -1 ){ + if(completionElementKindStack[i] == K_BETWEEN_ANNOTATION_NAME_AND_RPAREN) + return true; + i--; + } + return false; + +} protected boolean isIndirectlyInsideBlock(){ int i = elementPtr; while(i > -1) { @@ -3343,6 +3414,7 @@ this.assistNode = fr; this.lastCheckPoint = fr.sourceEnd + 1; identifierLengthPtr--; + populateCompletionElementKind(); if (isSuperAccess) { //considerates the fieldReference beginning at the 'super' .... fr.sourceStart = intStack[intPtr--]; fr.receiver = new SuperReference(fr.sourceStart, endPosition); @@ -3365,6 +3437,7 @@ /* generate a pseudo field with a completion on type reference */ currentElement.add( new CompletionOnFieldType(this.getTypeReference(0), false), 0); + populateCompletionElementKind(); return; } if (!diet) return; // only record references attached to types @@ -3537,6 +3610,7 @@ CompletionOnLocalName local = new CompletionOnLocalName(assistName, sourceStart, sourceEnd); this.assistNode = local; this.lastCheckPoint = sourceEnd + 1; + populateCompletionElementKind(); return local; } } @@ -3548,7 +3622,21 @@ CompletionOnFieldName field = new CompletionOnFieldName(assistName, sourceStart, sourceEnd); this.assistNode = field; this.lastCheckPoint = sourceEnd + 1; + populateCompletionElementKind(); return field; } } + +/** + * Record the element kind stack when we first hit the completion + * site. + */ +private void populateCompletionElementKind() +{ + if(this.completionElementKindStack == null && elementPtr >= 0){ + int len = elementPtr + 1; + this.completionElementKindStack = new int[len]; + System.arraycopy(this.elementKindStack, 0, this.completionElementKindStack, 0, len); + } +} } Index: compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java =================================================================== RCS file: /home/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java,v retrieving revision 1.37.2.3 diff -u -r1.37.2.3 Annotation.java --- compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java 3 Jun 2005 08:25:44 -0000 1.37.2.3 +++ compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java 2 Aug 2005 01:43:15 -0000 @@ -380,6 +380,8 @@ public SourceAnnotation getCompilerAnnotation() { + if( this.compilerAnnotation == null && this.resolvedType != null ) + this.compilerAnnotation = new SourceAnnotation(this); return this.compilerAnnotation; } Index: dom/org/eclipse/jdt/core/dom/ASTConverter.java =================================================================== RCS file: /home/eclipse/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java,v retrieving revision 1.202.2.3 diff -u -r1.202.2.3 ASTConverter.java --- dom/org/eclipse/jdt/core/dom/ASTConverter.java 1 Jul 2005 17:57:49 -0000 1.202.2.3 +++ dom/org/eclipse/jdt/core/dom/ASTConverter.java 2 Aug 2005 01:43:17 -0000 @@ -1432,6 +1432,8 @@ } public Expression convert(org.eclipse.jdt.internal.compiler.ast.Expression expression) { + if(expression == null) + return null; if ((expression.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) != 0) { return convertToParenthesizedExpression(expression); } @@ -4669,7 +4671,8 @@ int end = (int)(positions[0] & 0xFFFFFFFF); firstToken.setSourceRange(start, end - start + 1); final SimpleName secondToken = new SimpleName(this.ast); - secondToken.internalSetIdentifier(new String(typeName[1])); + final String secondID = length > 1 ? new String(typeName[1]) : ""; //$NON-NLS-1$ + secondToken.internalSetIdentifier(secondID); secondToken.index = 2; start = (int)(positions[1]>>>32); end = (int)(positions[1] & 0xFFFFFFFF); Index: dom/org/eclipse/jdt/core/dom/ResolvedAnnotation.java =================================================================== RCS file: /home/eclipse/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Attic/ResolvedAnnotation.java,v retrieving revision 1.1.2.2 diff -u -r1.1.2.2 ResolvedAnnotation.java --- dom/org/eclipse/jdt/core/dom/ResolvedAnnotation.java 12 May 2005 11:01:56 -0000 1.1.2.2 +++ dom/org/eclipse/jdt/core/dom/ResolvedAnnotation.java 2 Aug 2005 01:43:17 -0000 @@ -42,7 +42,10 @@ public ITypeBinding getAnnotationType() { final ITypeBinding binding = this.bindingResolver.getTypeBinding(this.internalAnnotation.getAnnotationType()); - return binding.isAnnotation() ? binding : null; + if( binding == null || !binding.isAnnotation() ) + return null; + else + return binding; } public IResolvedMemberValuePair[] getDeclaredMemberValuePairs() { Index: model/org/eclipse/jdt/core/JavaCore.java =================================================================== RCS file: /home/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java,v retrieving revision 1.450.2.6 diff -u -r1.450.2.6 JavaCore.java --- model/org/eclipse/jdt/core/JavaCore.java 1 Jul 2005 17:57:50 -0000 1.450.2.6 +++ model/org/eclipse/jdt/core/JavaCore.java 2 Aug 2005 01:43:18 -0000 @@ -65,6 +65,7 @@ import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jdt.core.compiler.ICompilationParticipant; +import org.eclipse.jdt.core.completion.ICompletionParticipant; import org.eclipse.jdt.core.search.IJavaSearchConstants; import org.eclipse.jdt.core.search.IJavaSearchScope; import org.eclipse.jdt.core.search.SearchEngine; @@ -1040,6 +1041,17 @@ public static void addCompilationParticipant(ICompilationParticipant icp, int eventMask) { JavaModelManager.getJavaModelManager().getCompilationParticipants().add(icp, eventMask); } + + /** + * Add a completion participant listener dynamically. It is not necessary + * to call this for listeners registered with the completionParticipant + * extension point. + * + * @param icp the listener + */ + public static void addCompletionParticipant(ICompletionParticipant icp) { + JavaModelManager.getJavaModelManager().getCompletionParticipantManager().add(icp); + } /** * Adds the given listener for changes to Java elements. @@ -1576,6 +1588,12 @@ return JavaModelManager.getJavaModelManager().getCompilationParticipants().getCompilationParticipants(eventMask, project); } + public static List getCompletionParticipants(final IJavaProject project ){ + return JavaModelManager.getJavaModelManager().getCompletionParticipantManager().getCompletionParticipants(project); + } + + + /** * Returns a table of all known configurable options with their default values. * These options allow to configure the behaviour of the underlying components. @@ -3707,6 +3725,17 @@ public static void removeCompilationParticipant(ICompilationParticipant icp) { JavaModelManager.getJavaModelManager().getCompilationParticipants().remove(icp); } + + /** + * Removes the specified completion participant listener. Has no effect + * if the listener was not on the list, or if it was registered via the + * compilationParticipant extension point rather than a call to + * addCompilationParticipant. + * @param icp the listener to remove + */ + public static void removeCompletionParticipant(ICompletionParticipant icp) { + JavaModelManager.getJavaModelManager().getCompletionParticipantManager().remove(icp); + } /** * Removes the given element changed listener. Index: model/org/eclipse/jdt/internal/core/JavaModelManager.java =================================================================== RCS file: /home/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java,v retrieving revision 1.256.2.5 diff -u -r1.256.2.5 JavaModelManager.java --- model/org/eclipse/jdt/internal/core/JavaModelManager.java 1 Jul 2005 17:57:49 -0000 1.256.2.5 +++ model/org/eclipse/jdt/internal/core/JavaModelManager.java 2 Aug 2005 01:43:20 -0000 @@ -29,6 +29,7 @@ import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.core.compiler.ICompilationParticipant; import org.eclipse.jdt.core.compiler.IProblem; +import org.eclipse.jdt.core.completion.ICompletionParticipant; import org.eclipse.jdt.internal.codeassist.CompletionEngine; import org.eclipse.jdt.internal.codeassist.SelectionEngine; import org.eclipse.jdt.internal.compiler.Compiler; @@ -125,6 +126,11 @@ public static final String COMPILATION_PARTICIPANT_EXTPOINT_ID = "compilationParticipant" ; //$NON-NLS-1$ /** + * Name of the extension point for contributing a completion participant + */ + public static final String COMPLETION_PARTICIPANT_EXTPOINT_ID = "completionParticipant" ; //$NON-NLS-1$ + + /** * Value of the content-type for Java source files */ public static final String JAVA_SOURCE_CONTENT_TYPE = JavaCore.PLUGIN_ID+".javaSource" ; //$NON-NLS-1$ @@ -296,8 +302,108 @@ } } + public class CompletionParticipantManager { + /** Set registered by plugins */ + private Set pluginCPs = null; + + /** Set > from calls to add() */ + private Set dynamicCPs = new HashSet(); + + /** + * @see JavaCore#addCompletionParticipant(ICompletionParticipant) + */ + public synchronized void add(ICompletionParticipant icp) { + dynamicCPs.add(icp); + } + + /** + * @see JavaCore#removeCompletionParticipant(ICompletionParticipant) + */ + public synchronized void remove(ICompletionParticipant icp) { + dynamicCPs.remove(icp); + } + + /** + * Returns an immutable list containing of registered + * listeners that have requested notification of code completion events + * for the given java project. + * The first time this is called, it loads listeners from plugins, + * which may cause plugins to be loaded. + * + *

+ * The initialization of ICompletionParticipants is synchronized. A deadlock may + * occur if all of the following conditions are true: + * + *

  • A plugin defines ICompletionParticipant
  • + *
  • That plugin's start() method spawns a thread which causes + * getCompletionParticipants() to be invoked
  • + *
  • The start() method blocks waiting for the spawned thread to complete.
  • + * + * Any completion event will cause getCompletionParticpants() to + * be called. + * + * @return an immutable List of ICompletionParticipants. + */ + public List getCompletionParticipants(final IJavaProject project) { + initPlugins(); + List filteredICPs = new ArrayList(); + + synchronized(this) { + for(Iterator it = dynamicCPs.iterator(); it.hasNext(); ){ + ICompletionParticipant participant = (ICompletionParticipant)it.next(); + if( participant.doesParticipateInProject(project)) + filteredICPs.add(participant); + } + } + + for(Iterator it = pluginCPs.iterator(); it.hasNext(); ){ + ICompletionParticipant participant = (ICompletionParticipant)it.next(); + if( participant.doesParticipateInProject(project)) + filteredICPs.add(participant); + } + + return Collections.unmodifiableList(filteredICPs); + } + + private synchronized void initPlugins() { + if (null != pluginCPs) { + return; + } + pluginCPs = new HashSet(); + + IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint( + JavaCore.PLUGIN_ID, COMPLETION_PARTICIPANT_EXTPOINT_ID); + if (extension == null) + return; + IExtension[] extensions = extension.getExtensions(); + for(int iExtension = 0; iExtension < extensions.length; iExtension++){ + // for all extensions of this point... + for(int i = 0; i < extensions.length; i++){ + IConfigurationElement [] configElements = extensions[i].getConfigurationElements(); + // for all config elements named "compilationParticipant" + for(int j = 0; j < configElements.length; j++){ + String elementName = configElements[j].getName(); + if (!(COMPLETION_PARTICIPANT_EXTPOINT_ID.equals(elementName))) { //$NON-NLS-1$ - name of configElement + continue; + } + try{ + Object execExt = configElements[j].createExecutableExtension("class"); //$NON-NLS-1$ - attribute class + pluginCPs.add(execExt); + } + catch(CoreException e) { + // TODO: what is the right way to handle exceptions? + e.printStackTrace(); + } + } + } + } + } + } + private final CompilationParticipants compilationParticipants = new CompilationParticipants(); + private final CompletionParticipantManager completionParticipants = new CompletionParticipantManager(); + /** * Returns whether the given full path (for a package) conflicts with the output location * of the given project. @@ -1171,6 +1277,10 @@ public CompilationParticipants getCompilationParticipants() { return compilationParticipants; } + + public CompletionParticipantManager getCompletionParticipantManager() { + return completionParticipants; + } public DeltaProcessor getDeltaProcessor() { return this.deltaState.getDeltaProcessor(); Index: codeassist/org/eclipse/jdt/internal/codeassist/JavaCompletionEvent.java =================================================================== RCS file: codeassist/org/eclipse/jdt/internal/codeassist/JavaCompletionEvent.java diff -N codeassist/org/eclipse/jdt/internal/codeassist/JavaCompletionEvent.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ codeassist/org/eclipse/jdt/internal/codeassist/JavaCompletionEvent.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,412 @@ +/******************************************************************************* + * Copyright (c) 2005 BEA Systems, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * tyeung@bea.com - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.codeassist; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.resources.IFile; +import org.eclipse.jdt.core.CompletionProposal; +import org.eclipse.jdt.core.CompletionRequestor; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.completion.ICompletionEvent; +import org.eclipse.jdt.core.completion.ICompletionParticipant; +import org.eclipse.jdt.internal.codeassist.complete.CompletionOnFieldType; +import org.eclipse.jdt.internal.codeassist.complete.CompletionOnMarkerAnnotationName; +import org.eclipse.jdt.internal.codeassist.complete.CompletionOnMethodReturnType; +import org.eclipse.jdt.internal.compiler.ast.ASTNode; +import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; +import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; +import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; + +class JavaCompletionEvent implements ICompletionEvent +{ + /** + * @param unit + * @param completionNode the node where code completion occurs + * @return the completion event or null if it cannot be created. + */ + static JavaCompletionEvent createCompletionEvent(final CompilationUnitDeclaration unit, + final ICompilationUnit workingCopy, + final ASTNode completionNode, + final CompilerOptions compilerOptions, + final char[] source, + final int actualCompletionPosition, + final IJavaProject javaProj, + final CompletionRequestor requestor) + { + if( unit == null || completionNode == null || + !(workingCopy instanceof org.eclipse.jdt.internal.core.CompilationUnit)) + return null; + final org.eclipse.jdt.internal.core.CompilationUnit internalUnit = + (org.eclipse.jdt.internal.core.CompilationUnit)workingCopy; + final org.eclipse.jdt.core.dom.CompilationUnit domUnit = + convert2Dom(source, unit, internalUnit, compilerOptions); + + final ASTNode tightCompletionNode = + getTighterNodeForCompletion(completionNode); + + final org.eclipse.jdt.core.dom.ASTNode domNode = findNodeByOffset(domUnit, actualCompletionPosition + 1); + + return new JavaCompletionEvent(tightCompletionNode, actualCompletionPosition + 1, + domNode, (IFile)internalUnit.getResource(), + javaProj, requestor); + } + + private final IFile ifile; + private final org.eclipse.jdt.core.dom.ASTNode domASTNode; + protected List filters = null; + private final CompletionRequestor requestor; + private final IJavaProject javaProj; + private final int actualCompletionPosition; + + + private JavaCompletionEvent(ASTNode internalNode, + int actualCompletionPosition, + org.eclipse.jdt.core.dom.ASTNode domNode, + IFile ifile, + IJavaProject proj, + CompletionRequestor requestor) + { + if( domNode == null ) + throw new IllegalArgumentException("domNode cannot be null"); //$NON-NLS-1$ + this.domASTNode = domNode; + this.ifile = ifile; + this.actualCompletionPosition = actualCompletionPosition; + this.javaProj = proj; + this.requestor = requestor; + } + + public IFile getIFile() + { + return ifile; + } + + public int getCompletionOffset() + { + return this.actualCompletionPosition; + } + + public IJavaProject getJavaProject(){ + return this.javaProj; + } + + public org.eclipse.jdt.core.dom.ASTNode getRecoveredASTNode(){ + return domASTNode; + } + + public boolean ignore(int proposalType){ + return this.requestor.isIgnored(proposalType); + } + + public void accept(CompletionProposal proposal){ + if( proposal == null || ignore(proposal.getKind()) ) return; + //noProposal = false; + this.requestor.accept(proposal); + } + + protected void addFilter(ICompletionParticipant.ICompletionFilter filter){ + if( filter == null ) return; + if( filters == null ) + filters = new ArrayList(4); + filters.add(filter); + } + + private static ASTNode getTighterNodeForCompletion(final ASTNode astNode ) + { + ASTNode result = astNode; + if (astNode instanceof CompletionOnFieldType) { + CompletionOnFieldType field = (CompletionOnFieldType) astNode; + result = field.type; + } + else if( astNode instanceof CompletionOnMethodReturnType ){ + CompletionOnMethodReturnType method = (CompletionOnMethodReturnType) astNode; + result = method.returnType; + } + else if(astNode instanceof CompletionOnMarkerAnnotationName) { + CompletionOnMarkerAnnotationName annot = (CompletionOnMarkerAnnotationName) astNode; + result = annot.type; + } + return result; + } + + private static org.eclipse.jdt.core.dom.CompilationUnit convert2Dom( + final char[] source, + final CompilationUnitDeclaration unit, + final org.eclipse.jdt.internal.core.CompilationUnit workingCopy, + final CompilerOptions compilerOptions){ + + return org.eclipse.jdt.core.dom.AST.convertCompilationUnit( + org.eclipse.jdt.core.dom.AST.JLS3, unit, source, + compilerOptions.getMap(), + true, workingCopy, null); + } + + private static org.eclipse.jdt.core.dom.ASTNode findNodeByOffset( + final org.eclipse.jdt.core.dom.ASTNode node, + final int target) + { + final int nodeStart = node.getStartPosition(); + final int nodeEnd = nodeStart + node.getLength(); + + // 'node' is a possible best match + if( nodeStart <= target && nodeEnd >= target) { + + List children = getChildren(node); + for( int i=0, len = children.size(); i= nodeStart && newEnd <= nodeEnd ) + // If we find it in the current sub-tree, we will not + // look into anything further. + return newNode; + } + } + return node; + + } + else + return null; + } + + private static List getChildren(final org.eclipse.jdt.core.dom.ASTNode parent ) + { + class ChildrenVisitor extends org.eclipse.jdt.core.dom.ASTVisitor + { + private final List list; + ChildrenVisitor(){ list = new ArrayList(); } + public List getChildren(){ return list; } + public boolean visit(org.eclipse.jdt.core.dom.AnnotationTypeDeclaration node) + { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.AnonymousClassDeclaration node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.ArrayAccess node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.ArrayCreation node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.ArrayInitializer node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.ArrayType node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.AssertStatement node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.Assignment node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.Block node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.BlockComment node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.BooleanLiteral node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.BreakStatement node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.CastExpression node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.CatchClause node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.CharacterLiteral node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.ClassInstanceCreation node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.CompilationUnit node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.ConditionalExpression node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.ConstructorInvocation node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.ContinueStatement node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.DoStatement node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.EmptyStatement node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.EnhancedForStatement node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.EnumConstantDeclaration node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.EnumDeclaration node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.ExpressionStatement node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.FieldAccess node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.FieldDeclaration node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.ForStatement node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.Javadoc node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.IfStatement node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.ImportDeclaration node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.InfixExpression node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.InstanceofExpression node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.Initializer node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.LabeledStatement node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.MarkerAnnotation node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.MemberRef node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.MemberValuePair node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.MethodRef node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.MethodRefParameter node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.MethodDeclaration node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.MethodInvocation node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.Modifier node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.NormalAnnotation node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.NullLiteral node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.NumberLiteral node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.PackageDeclaration node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.ParameterizedType node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.ParenthesizedExpression node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.PostfixExpression node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.PrefixExpression node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.PrimitiveType node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.QualifiedName node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.QualifiedType node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.ReturnStatement node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.SimpleName node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.SimpleType node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.SingleMemberAnnotation node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.SingleVariableDeclaration node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.StringLiteral node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.SuperConstructorInvocation node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.SuperFieldAccess node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.SuperMethodInvocation node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.SwitchCase node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.SwitchStatement node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.SynchronizedStatement node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.TagElement node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.TextElement node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.ThisExpression node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.ThrowStatement node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.TryStatement node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.TypeDeclaration node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.TypeDeclarationStatement node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.TypeLiteral node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.TypeParameter node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.WhileStatement node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.WildcardType node) { return internalVisit(node); } + + private boolean internalVisit(org.eclipse.jdt.core.dom.ASTNode node){ + if( node == parent ) + return true; + list.add(node); + return false; + } + } + + final ChildrenVisitor visitor = new ChildrenVisitor(); + parent.accept(visitor); + return visitor.getChildren(); + } + +/* + private static org.eclipse.jdt.core.dom.ASTNode findNodeByOffset( + org.eclipse.jdt.core.dom.CompilationUnit unit, + final int start){ + + class OffsetVisitor extends org.eclipse.jdt.core.dom.ASTVisitor { + org.eclipse.jdt.core.dom.ASTNode result = null; + + public boolean visit(org.eclipse.jdt.core.dom.AnnotationTypeDeclaration node) + { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.AnonymousClassDeclaration node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.ArrayAccess node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.ArrayCreation node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.ArrayInitializer node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.ArrayType node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.AssertStatement node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.Assignment node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.Block node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.BlockComment node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.BooleanLiteral node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.BreakStatement node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.CastExpression node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.CatchClause node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.CharacterLiteral node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.ClassInstanceCreation node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.CompilationUnit node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.ConditionalExpression node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.ConstructorInvocation node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.ContinueStatement node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.DoStatement node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.EmptyStatement node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.EnhancedForStatement node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.EnumConstantDeclaration node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.EnumDeclaration node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.ExpressionStatement node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.FieldAccess node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.FieldDeclaration node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.ForStatement node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.Javadoc node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.IfStatement node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.ImportDeclaration node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.InfixExpression node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.InstanceofExpression node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.Initializer node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.LabeledStatement node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.MarkerAnnotation node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.MemberRef node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.MemberValuePair node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.MethodRef node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.MethodRefParameter node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.MethodDeclaration node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.MethodInvocation node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.Modifier node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.NormalAnnotation node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.NullLiteral node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.NumberLiteral node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.PackageDeclaration node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.ParameterizedType node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.ParenthesizedExpression node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.PostfixExpression node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.PrefixExpression node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.PrimitiveType node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.QualifiedName node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.QualifiedType node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.ReturnStatement node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.SimpleName node){ return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.SimpleType node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.SingleMemberAnnotation node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.SingleVariableDeclaration node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.StringLiteral node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.SuperConstructorInvocation node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.SuperFieldAccess node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.SuperMethodInvocation node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.SwitchCase node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.SwitchStatement node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.SynchronizedStatement node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.TagElement node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.TextElement node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.ThisExpression node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.ThrowStatement node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.TryStatement node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.TypeDeclaration node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.TypeDeclarationStatement node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.TypeLiteral node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.TypeParameter node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.WhileStatement node) { return internalVisit(node); } + public boolean visit(org.eclipse.jdt.core.dom.WildcardType node) { return internalVisit(node); } + + private boolean internalVisit(org.eclipse.jdt.core.dom.ASTNode node){ + final int nodeStart = node.getStartPosition(); + final int nodeEnd = nodeStart + node.getLength(); + + // some node we should consider + if( nodeStart <= start && nodeEnd >= start) { + // is it a tighter match + if( result != null ){ + final int curResultStart = result.getStartPosition(); + final int curResultEnd = result.getLength() + curResultStart; + // end is inclusive to account for 0 length node. + if( nodeStart >= curResultStart && nodeEnd <= curResultEnd) + result = node; + } + else + result = node; + + return true; + } + else + return false; + } + } + + final OffsetVisitor visitor = new OffsetVisitor(); + unit.accept(visitor); + return visitor.result; + } + */ +} + + + Index: model/org/eclipse/jdt/core/completion/ICompletionEvent.java =================================================================== RCS file: model/org/eclipse/jdt/core/completion/ICompletionEvent.java diff -N model/org/eclipse/jdt/core/completion/ICompletionEvent.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ model/org/eclipse/jdt/core/completion/ICompletionEvent.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright (c) 2005 BEA Systems, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * tyeung@bea.com - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.completion; + +import org.eclipse.core.resources.IFile; +import org.eclipse.jdt.core.CompletionProposal; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.dom.ASTNode; + +/** + * A code completion event. This provide the context where completion is requested as + * well as access to the type system and project environment. + * + * @see ICompletionParticipant#complete(ICompletionEvent e) + */ +public interface ICompletionEvent { + + /** + * @return the current java project that the event occured. + */ + IJavaProject getJavaProject(); + + /** + * @return the file where the completion is happening + */ + IFile getIFile(); + + /** + * The ast node where completion is requested and this + * reflects the node seen by the error recovery parser or + * in some case, the node expected by the error recovery parser. + * ICompletionParticipant should use this + * as a reference but not a definite answer. + * + * @return the ast node where completion is requested. + */ + ASTNode getRecoveredASTNode(); + + /** + * @return the offset where completion is requested. + */ + int getCompletionOffset(); + + /** + * Used by clients to determine the type of completion requested. + * Clients should only propose completions whose type is not + * ignored. i.e. When this method is invoked on the proposal's type, it + * should always return true + * + * @param proposalType one of CompletionProposal + * @return true iff the given type of completion proposal is + * required. Return false + */ + boolean ignore(int proposalType); + + /** + * Reporting a completion proposal. The type of the proposal + * should not be one of those ignored type. If so, the proposal + * will simply be dropped. + * + * @param propsoal the proposed completion. + * @see #ignore(int) + */ + void accept(CompletionProposal propsoal); +} Index: model/org/eclipse/jdt/core/completion/ICompletionParticipant.java =================================================================== RCS file: model/org/eclipse/jdt/core/completion/ICompletionParticipant.java diff -N model/org/eclipse/jdt/core/completion/ICompletionParticipant.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ model/org/eclipse/jdt/core/completion/ICompletionParticipant.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,109 @@ +/******************************************************************************* + * Copyright (c) 2005 BEA Systems, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * tyeung@bea.com - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.completion; + +import org.eclipse.jdt.core.CompletionProposal; +import org.eclipse.jdt.core.IJavaProject; + +/** + * Interface to be implemented by client that wants to participate in the + * code completion process. All registered participants will be consulted + * for completion proposal when code assist is requested. Participants will + * also be given a chance to filter out jdt proposed completions. + * + * Completion participants are registered through the extension point + * "org.eclipse.jdt.core.completionParticipant". + */ +public interface ICompletionParticipant { + + /** + * Indicate participant is interested in all completion events. + */ + public static final int COMPLETION_ALL = 0xFFFF ; + /** + * Indicate participant is interested only in completion inside annotation. + */ + public static final int COMPLETION_INSIDE_ANNOTATION = 0x01; + + + /** + * During completion, this method is called on the completion + * participant to discover if it is interested in this project.

    + * + * For efficiency, participants that are not interested in a + * given project should return false for that project.

    + */ + public boolean doesParticipateInProject( IJavaProject project ); + + /** + * During completion, this method is called on the completion participant + * to discover the type of completion event that it is interested to + * participate. + * + * The return value should be the logical OR of one or all of the constants + * defined above. + * {@link #complete(ICompletionEvent) } and {@link #getCompletionFilter(ICompletionEvent)} + * will only be invoked if this call returns a value that matches the completion event + * that are to occur. + * + * @return the logical OR of event mask that it is interested to participate. + */ + public int getSupportedEventMask(); + + /** + * Called when completion are requested and participant has expressed + * interest in the event. + * This method is guaranteed to be called only once per + * completion event that it participates in. + * Participants will be asked to filter jdt compiler proposals first + * before given a chance to proposal completions of their own. + * + * @param event the completion event + * @see #getCompletionFilter(ICompletionEvent) + * @see #getSupportedEventMask() + * @see #doesParticipateInProject(IJavaProject) + */ + void complete(ICompletionEvent event); + + /** + * Allow participant to filter out completion proposal generated by the jdt compiler. + * If null is returned all completion proposals generated by + * the jdt compiler will be included in the final list of proposal iff + * accepted. + * + * This method is guaranteed to be called only once per completion event + * that it participates in. And the same completion filter will be used + * to filter all proposals generated by the jdt compiler. + * + * @param event the completion event + * @return null to indicate acceptance of all jdt + * proposed compiler or a completion filter examine jdt proposed completions. + * @see #doesParticipateInProject(IJavaProject) + * @see #getSupportedEventMask() + */ + ICompletionFilter getCompletionFilter(ICompletionEvent event); + + /** + * Called when the completion event is done. + * @param event the completion event + */ + void endOfEvent(ICompletionEvent event); + + interface ICompletionFilter{ + + /** + * @param proposal generated by the jdt compiler. + * @return true to indicate proposal should be included and + * false to indicate proposal should be excluded. + */ + boolean accept(CompletionProposal proposal); + } +}