KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > template > java > CompilationUnitCompletion


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.corext.template.java;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Arrays JavaDoc;
15 import java.util.HashMap JavaDoc;
16 import java.util.List JavaDoc;
17 import java.util.ListIterator JavaDoc;
18 import java.util.Map JavaDoc;
19
20 import org.eclipse.core.runtime.Assert;
21 import org.eclipse.core.runtime.CoreException;
22 import org.eclipse.core.runtime.IStatus;
23 import org.eclipse.core.runtime.Status;
24
25
26 import org.eclipse.jdt.core.CompletionProposal;
27 import org.eclipse.jdt.core.CompletionRequestor;
28 import org.eclipse.jdt.core.ICompilationUnit;
29 import org.eclipse.jdt.core.IJavaProject;
30 import org.eclipse.jdt.core.IType;
31 import org.eclipse.jdt.core.ITypeHierarchy;
32 import org.eclipse.jdt.core.ITypeParameter;
33 import org.eclipse.jdt.core.JavaModelException;
34 import org.eclipse.jdt.core.Signature;
35 import org.eclipse.jdt.core.compiler.IProblem;
36
37 import org.eclipse.jdt.internal.ui.JavaPlugin;
38
39 /**
40  * A completion requester to collect informations on local variables.
41  * This class is used for guessing variable names like arrays, collections, etc.
42  */

43 final class CompilationUnitCompletion extends CompletionRequestor {
44
45     /**
46      * Describes a local variable (including parameters) inside the method where
47      * code completion was invoked. Special predicates exist to query whether
48      * a variable can be iterated over.
49      */

50     public final class Variable {
51         private static final int UNKNOWN= 0, NONE= 0;
52         private static final int ARRAY= 1;
53         private static final int COLLECTION= 2;
54         private static final int ITERABLE= 4;
55         
56         /**
57          * The name of the local variable.
58          */

59         private final String JavaDoc name;
60         
61         /**
62          * The signature of the local variable's type.
63          */

64         private final String JavaDoc signature;
65         
66         /* lazily computed properties */
67         private int fType= UNKNOWN;
68         private int fChecked= NONE;
69         private String JavaDoc[] fMemberTypes;
70         
71         private Variable(String JavaDoc name, String JavaDoc signature) {
72             this.name= name;
73             this.signature= signature;
74         }
75
76         /**
77          * Returns the name of the variable.
78          *
79          * @return the name of the variable
80          */

81         public String JavaDoc getName() {
82             return name;
83         }
84         
85         /**
86          * Returns <code>true</code> if the type of the local variable is an
87          * array type.
88          *
89          * @return <code>true</code> if the receiver's type is an array,
90          * <code>false</code> if not
91          */

92         public boolean isArray() {
93             if (fType == UNKNOWN && (fChecked & ARRAY) == 0 && Signature.getTypeSignatureKind(signature) == Signature.ARRAY_TYPE_SIGNATURE)
94                 fType= ARRAY;
95             fChecked |= ARRAY;
96             return fType == ARRAY;
97         }
98
99         /**
100          * Returns <code>true</code> if the receiver's type is a subclass of
101          * <code>java.util.Collection</code>, <code>false</code> otherwise.
102          *
103          * @return <code>true</code> if the receiver's type is a subclass of
104          * <code>java.util.Collection</code>, <code>false</code>
105          * otherwise
106          */

107         public boolean isCollection() {
108             // Collection extends Iterable
109
if ((fType == UNKNOWN || fType == ITERABLE) && (fChecked & COLLECTION) == 0 && isSubtypeOf("java.util.Collection")) //$NON-NLS-1$
110
fType= COLLECTION;
111             fChecked |= COLLECTION;
112             return fType == COLLECTION;
113         }
114         
115         /**
116          * Returns <code>true</code> if the receiver's type is a subclass of
117          * <code>java.lang.Iterable</code>, <code>false</code> otherwise.
118          *
119          * @return <code>true</code> if the receiver's type is a subclass of
120          * <code>java.lang.Iterable</code>, <code>false</code>
121          * otherwise
122          */

123         public boolean isIterable() {
124             if (fType == UNKNOWN && (fChecked & ITERABLE) == 0 && isSubtypeOf("java.lang.Iterable")) //$NON-NLS-1$
125
fType= ITERABLE;
126             fChecked |= ITERABLE;
127             return fType == ITERABLE || fType == COLLECTION; // Collection extends Iterable
128
}
129
130         /**
131          * Returns <code>true</code> if the receiver's type is an implementor
132          * of <code>interfaceName</code>.
133          *
134          * @param supertype the fully qualified name of the interface
135          * @return <code>true</code> if the receiver's type implements the
136          * type named <code>interfaceName</code>
137          */

138         private boolean isSubtypeOf(String JavaDoc supertype) {
139             String JavaDoc implementorName= SignatureUtil.stripSignatureToFQN(signature);
140             if (implementorName.length() == 0)
141                 return false;
142             
143             boolean qualified= supertype.indexOf('.') != -1;
144             
145             // try cheap test first
146
if (implementorName.equals(supertype) || !qualified && Signature.getSimpleName(implementorName).equals(supertype))
147                 return true;
148
149             if (fUnit == null)
150                 return false;
151
152             IJavaProject project= fUnit.getJavaProject();
153
154             try {
155                 IType sub= project.findType(implementorName);
156                 if (sub == null)
157                     return false;
158                 
159                 if (qualified) {
160                     IType sup= project.findType(supertype);
161                     if (sup == null)
162                         return false;
163                     ITypeHierarchy hierarchy= sub.newSupertypeHierarchy(null);
164                     return hierarchy.contains(sup);
165                 } else {
166                     ITypeHierarchy hierarchy= sub.newSupertypeHierarchy(null);
167                     IType[] allTypes= hierarchy.getAllTypes();
168                     for (int i= 0; i < allTypes.length; i++) {
169                         IType type= allTypes[i];
170                         if (type.getElementName().equals(supertype))
171                             return true;
172                     }
173                 }
174
175             } catch (JavaModelException e) {
176                 // ignore and return false
177
}
178             
179             return false;
180         }
181         
182         private IType[] getSupertypes(String JavaDoc supertype) {
183             IType[] empty= new IType[0];
184             String JavaDoc implementorName= SignatureUtil.stripSignatureToFQN(signature);
185             if (implementorName.length() == 0)
186                 return empty;
187             
188             boolean qualified= supertype.indexOf('.') != -1;
189
190             if (fUnit == null)
191                 return empty;
192             
193             IJavaProject project= fUnit.getJavaProject();
194             
195             try {
196                 IType sub= project.findType(implementorName);
197                 if (sub == null)
198                     return empty;
199                 
200                 if (qualified) {
201                     IType sup= project.findType(supertype);
202                     if (sup == null)
203                         return empty;
204                     return new IType[] {sup};
205                 } else {
206                     ITypeHierarchy hierarchy= sub.newSupertypeHierarchy(null);
207                     IType[] allTypes= hierarchy.getAllTypes();
208                     List JavaDoc matches= new ArrayList JavaDoc();
209                     for (int i= 0; i < allTypes.length; i++) {
210                         IType type= allTypes[i];
211                         if (type.getElementName().equals(supertype))
212                             matches.add(type);
213                     }
214                     return (IType[]) matches.toArray(new IType[matches.size()]);
215                 }
216                 
217             } catch (JavaModelException e) {
218                 // ignore and return false
219
}
220             
221             return empty;
222         }
223
224         /**
225          * Returns the signature of the member type.
226          *
227          * @return the signature of the member type
228          */

229         public String JavaDoc getMemberTypeSignature() {
230             return getMemberTypeSignatures()[0];
231         }
232         
233         /**
234          * Returns the signatures of all member type bounds.
235          *
236          * @return the signatures of all member type bounds
237          */

238         public String JavaDoc[] getMemberTypeSignatures() {
239             if (isArray()) {
240                 return new String JavaDoc[] {Signature.createArraySignature(Signature.getElementType(signature), Signature.getArrayCount(signature) - 1)};
241             } else if (fUnit != null && (isIterable() || isCollection())) {
242                 if (fMemberTypes == null) {
243                     try {
244                         try {
245                             TypeParameterResolver util= new TypeParameterResolver(this);
246                             fMemberTypes= util.computeBinding("java.lang.Iterable", 0); //$NON-NLS-1$
247
} catch (JavaModelException e) {
248                             try {
249                                 TypeParameterResolver util= new TypeParameterResolver(this);
250                                 fMemberTypes= util.computeBinding("java.util.Collection", 0); //$NON-NLS-1$
251
} catch (JavaModelException x) {
252                                 fMemberTypes= new String JavaDoc[0];
253                             }
254                         }
255                     } catch (IndexOutOfBoundsException JavaDoc e) {
256                         fMemberTypes= new String JavaDoc[0];
257                     }
258                 }
259                 if (fMemberTypes.length > 0)
260                     return fMemberTypes;
261             }
262             return new String JavaDoc[] {Signature.createTypeSignature("java.lang.Object", true)}; //$NON-NLS-1$
263
}
264         
265         /**
266          * Returns the type names of all member type bounds, as they would be
267          * appear when referenced in the current compilation unit.
268          *
269          * @return type names of all member type bounds
270          */

271         public String JavaDoc[] getMemberTypeNames() {
272             String JavaDoc[] signatures= getMemberTypeSignatures();
273             String JavaDoc[] names= new String JavaDoc[signatures.length];
274             
275             for (int i= 0; i < signatures.length; i++) {
276                 String JavaDoc sig= signatures[i];
277                 String JavaDoc local= (String JavaDoc) fLocalTypes.get(Signature.getElementType(sig));
278                 int dim= Signature.getArrayCount(sig);
279                 if (local != null && dim > 0) {
280                     StringBuffer JavaDoc array= new StringBuffer JavaDoc(local);
281                     for (int j= 0; j < dim; j++)
282                         array.append("[]"); //$NON-NLS-1$
283
local= array.toString();
284                 }
285                 if (local != null)
286                     names[i]= local;
287                 else
288                     names[i]= Signature.getSimpleName(Signature.getSignatureSimpleName(sig));
289             }
290             return names;
291         }
292
293         /**
294          * Returns the type arguments of the declared type of the variable. Returns
295          * an empty array if it is not a parameterized type.
296          *
297          * @param type the fully qualified type name of which to match a type argument
298          * @param index the index of the type parameter in the type
299          * @return the type bounds for the specified type argument in this local variable
300          * @since 3.3
301          */

302         public String JavaDoc[] getTypeArgumentBoundSignatures(String JavaDoc type, int index) {
303             List JavaDoc all= new ArrayList JavaDoc();
304             IType[] supertypes= getSupertypes(type);
305             if (fUnit != null) {
306                 for (int i= 0; i < supertypes.length; i++) {
307                     try {
308                         TypeParameterResolver util= new TypeParameterResolver(this);
309                         String JavaDoc[] result= util.computeBinding(supertypes[i].getFullyQualifiedName(), index);
310                         all.addAll(Arrays.asList(result));
311                     } catch (JavaModelException e) {
312                     } catch (IndexOutOfBoundsException JavaDoc e) {
313                     }
314                 }
315             }
316             if (all.isEmpty())
317                 return new String JavaDoc[] {Signature.createTypeSignature("java.lang.Object", true)}; //$NON-NLS-1$
318
return (String JavaDoc[]) all.toArray(new String JavaDoc[all.size()]);
319         }
320
321         /*
322          * @see java.lang.Object#toString()
323          */

324         public String JavaDoc toString() {
325             String JavaDoc type;
326             switch (fType) {
327                 case ITERABLE:
328                     type= "ITERABLE"; //$NON-NLS-1$
329
break;
330                 case COLLECTION:
331                     type= "COLLECTION"; //$NON-NLS-1$
332
break;
333                 case ARRAY:
334                     type= "ARRAY"; //$NON-NLS-1$
335
break;
336                 default:
337                     type= "UNKNOWN"; //$NON-NLS-1$
338
break;
339             }
340             return "LocalVariable [name=\"" + name + "\" signature=\"" + signature + "\" type=\"" + type + "\" member=\"" + getMemberTypeSignature() + "\"]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
341
}
342     }
343     
344     /**
345      * Given a java type, a resolver computes the bounds of type variables
346      * declared in a super type, considering any type constraints along the
347      * inheritance path.
348      */

349     private final class TypeParameterResolver {
350         private static final String JavaDoc OBJECT_SIGNATURE= "Ljava.lang.Object;"; //$NON-NLS-1$
351

352         private final ITypeHierarchy fHierarchy;
353         private final Variable fVariable;
354         private final IType fType;
355         private final List JavaDoc fBounds= new ArrayList JavaDoc();
356
357         /**
358          * Creates a new type parameter resolver to compute the bindings of type
359          * parameters for the declared type of <code>variable</code>. For any
360          * super type of the type of <code>variable</code>, calling
361          * {@link #computeBinding(IType, int) computeBinding} will find the type
362          * bounds of type variables in the super type, considering any type
363          * constraints along the inheritance path.
364          *
365          * @param variable the local variable under investigation
366          * @throws JavaModelException if the type of <code>variable</code>
367          * cannot be found
368          */

369         public TypeParameterResolver(Variable variable) throws JavaModelException {
370             String JavaDoc typeName= SignatureUtil.stripSignatureToFQN(variable.signature);
371             IJavaProject project= fUnit.getJavaProject();
372             fType= project.findType(typeName);
373             fHierarchy= fType.newSupertypeHierarchy(null);
374             fVariable= variable;
375         }
376         
377         /**
378          * Given a type parameter of <code>superType</code> at position
379          * <code>index</code>, this method computes and returns the (lower)
380          * type bound(s) of that parameter for an instance of <code>fType</code>.
381          * <p>
382          * <code>superType</code> must be a super type of <code>fType</code>,
383          * and <code>superType</code> must have at least
384          * <code>index + 1</code> type parameters.
385          * </p>
386          *
387          * @param superType the qualified type name of the super type to compute
388          * the type parameter binding for
389          * @param index the index into the list of type parameters of
390          * <code>superType</code>
391          * @throws JavaModelException if any java model operation fails
392          * @throws IndexOutOfBoundsException if the index is not valid
393          */

394         public String JavaDoc[] computeBinding(String JavaDoc superType, int index) throws JavaModelException, IndexOutOfBoundsException JavaDoc {
395             IJavaProject project= fUnit.getJavaProject();
396             IType type= project.findType(superType);
397             if (type == null)
398                 throw new JavaModelException(new CoreException(new Status(IStatus.ERROR, JavaPlugin.getPluginId(), IStatus.OK, "No such type", null))); //$NON-NLS-1$
399
return computeBinding(type, index);
400         }
401
402         /**
403          * Given a type parameter of <code>superType</code> at position
404          * <code>index</code>, this method computes and returns the (lower)
405          * type bound(s) of that parameter for an instance of <code>fType</code>.
406          * <p>
407          * <code>superType</code> must be a super type of <code>fType</code>,
408          * and <code>superType</code> must have at least
409          * <code>index + 1</code> type parameters.
410          * </p>
411          *
412          * @param superType the super type to compute the type parameter binding
413          * for
414          * @param index the index into the list of type parameters of
415          * <code>superType</code>
416          * @throws JavaModelException if any java model operation fails
417          * @throws IndexOutOfBoundsException if the index is not valid
418          */

419         public String JavaDoc[] computeBinding(IType superType, int index) throws JavaModelException, IndexOutOfBoundsException JavaDoc {
420             initBounds();
421             computeTypeParameterBinding(superType, index);
422             return (String JavaDoc[]) fBounds.toArray(new String JavaDoc[fBounds.size()]);
423         }
424         
425         /**
426          * Given a type parameter of <code>superType</code> at position
427          * <code>index</code>, this method recursively computes the (lower)
428          * type bound(s) of that parameter for an instance of <code>fType</code>.
429          * <p>
430          * <code>superType</code> must be a super type of <code>fType</code>,
431          * and <code>superType</code> must have at least
432          * <code>index + 1</code> type parameters.
433          * </p>
434          * <p>
435          * The type bounds are stored in <code>fBounds</code>.
436          * </p>
437          *
438          * @param superType the super type to compute the type parameter binding
439          * for
440          * @param index the index into the list of type parameters of
441          * <code>superType</code>
442          * @throws JavaModelException if any java model operation fails
443          * @throws IndexOutOfBoundsException if the index is not valid
444          */

445         private void computeTypeParameterBinding(final IType superType, final int index) throws JavaModelException, IndexOutOfBoundsException JavaDoc {
446             int nParameters= superType.getTypeParameters().length;
447             if (nParameters <= index)
448                 throw new IndexOutOfBoundsException JavaDoc();
449             
450             IType[] subTypes= fHierarchy.getSubtypes(superType);
451             
452             if (subTypes.length == 0) {
453                 // we have reached down to the base type
454
Assert.isTrue(superType.equals(fType));
455                 
456                 String JavaDoc match= findMatchingTypeArgument(fVariable.signature, index, fUnit.findPrimaryType());
457                 String JavaDoc bound= SignatureUtil.getUpperBound(match);
458                 
459                 // use the match whether it is a concrete type or not - if not,
460
// the generic type will at least be in visible in our context
461
// and can be referenced
462
addBound(bound);
463                 return;
464             }
465             
466             IType subType= subTypes[0]; // take the first, as they all lead to fType
467

468             String JavaDoc signature= findMatchingSuperTypeSignature(subType, superType);
469             String JavaDoc match= findMatchingTypeArgument(signature, index, subType);
470             
471             if (isConcreteType(match, subType)) {
472                 addBound(match);
473                 return;
474             }
475             
476             ITypeParameter[] typeParameters= subType.getTypeParameters();
477             
478             for (int k= 0; k < typeParameters.length; k++) {
479                 ITypeParameter formalParameter= typeParameters[k];
480                 if (formalParameter.getElementName().equals(SignatureUtil.stripSignatureToFQN(match))) {
481                     String JavaDoc[] bounds= formalParameter.getBounds();
482                     for (int i= 0; i < bounds.length; i++) {
483                         String JavaDoc boundSignature= Signature.createTypeSignature(bounds[i], true);
484                         addBound(SignatureUtil.qualifySignature(boundSignature, subType));
485                     }
486                     computeTypeParameterBinding(subType, k);
487                     return;
488                 }
489             }
490             
491             // We have a non-concrete type argument T, but no matching type
492
// parameter in the sub type. This can happen if T is declared in
493
// the enclosing type. Since it the declaration is probably visible
494
// then, its fine to simply copy the match to the bounds and return.
495
addBound(match);
496             return;
497         }
498
499         /**
500          * Finds and returns the type argument with index <code>index</code>
501          * in the given type super type signature. If <code>signature</code>
502          * is a generic signature, the type parameter at <code>index</code> is
503          * extracted. If the type parameter is an upper bound (<code>? super SomeType</code>),
504          * the type signature of <code>java.lang.Object</code> is returned.
505          * <p>
506          * Also, if <code>signature</code> has no type parameters (i.e. is a
507          * reference to the raw type), the type signature of
508          * <code>java.lang.Object</code> is returned.
509          * </p>
510          *
511          * @param signature the super type signature from a type's
512          * <code>extends</code> or <code>implements</code> clause
513          * @param index the index of the type parameter to extract from
514          * <code>signature</code>
515          * @param context the type context inside which unqualified types should
516          * be resolved
517          * @return the type argument signature of the type parameter at
518          * <code>index</code> in <code>signature</code>
519          * @throws IndexOutOfBoundsException if the index is not valid
520          */

521         private String JavaDoc findMatchingTypeArgument(String JavaDoc signature, int index, IType context) throws IndexOutOfBoundsException JavaDoc {
522             String JavaDoc[] typeArguments= Signature.getTypeArguments(signature);
523             if (typeArguments.length > 0 && typeArguments.length <= index)
524                 throw new IndexOutOfBoundsException JavaDoc();
525             if (typeArguments.length == 0) {
526                 // raw binding - bound to Object
527
return OBJECT_SIGNATURE;
528             } else {
529                 String JavaDoc bound= SignatureUtil.getUpperBound(typeArguments[index]);
530                 return SignatureUtil.qualifySignature(bound, context);
531             }
532         }
533
534         /**
535          * Finds and returns the super type signature in the
536          * <code>extends</code> or <code>implements</code> clause of
537          * <code>subType</code> that corresponds to <code>superType</code>.
538          *
539          * @param subType a direct and true sub type of <code>superType</code>
540          * @param superType a direct super type (super class or interface) of
541          * <code>subType</code>
542          * @return the super type signature of <code>subType</code> referring
543          * to <code>superType</code>
544          * @throws JavaModelException if extracting the super type signatures
545          * fails, or if <code>subType</code> contains no super type
546          * signature to <code>superType</code>
547          */

548         private String JavaDoc findMatchingSuperTypeSignature(IType subType, IType superType) throws JavaModelException {
549             String JavaDoc[] signatures= getSuperTypeSignatures(subType, superType);
550             for (int i= 0; i < signatures.length; i++) {
551                 String JavaDoc signature= signatures[i];
552                 String JavaDoc qualified= SignatureUtil.qualifySignature(signature, subType);
553                 String JavaDoc subFQN= SignatureUtil.stripSignatureToFQN(qualified);
554                 
555                 String JavaDoc superFQN= superType.getFullyQualifiedName();
556                 if (subFQN.equals(superFQN)) {
557                     return signature;
558                 }
559                 
560                 // handle local types
561
if (fLocalTypes.containsValue(subFQN)) {
562                     return signature;
563                 }
564             }
565             
566             throw new JavaModelException(new CoreException(new Status(IStatus.ERROR, JavaPlugin.getPluginId(), IStatus.OK, "Illegal hierarchy", null))); //$NON-NLS-1$
567
}
568         
569         /**
570          * Returns the super interface signatures of <code>subType</code> if
571          * <code>superType</code> is an interface, otherwise returns the super
572          * type signature.
573          *
574          * @param subType the sub type signature
575          * @param superType the super type signature
576          * @return the super type signatures of <code>subType</code>
577          * @throws JavaModelException if any java model operation fails
578          */

579         private String JavaDoc[] getSuperTypeSignatures(IType subType, IType superType) throws JavaModelException {
580             if (superType.isInterface())
581                 return subType.getSuperInterfaceTypeSignatures();
582             else
583                 return new String JavaDoc[] {subType.getSuperclassTypeSignature()};
584         }
585         
586         /**
587          * Clears the collected type bounds and initializes it with
588          * <code>java.lang.Object</code>.
589          */

590         private void initBounds() {
591             fBounds.clear();
592             fBounds.add(OBJECT_SIGNATURE);
593         }
594
595         /**
596          * Filters the current list of type bounds through the additional type
597          * bound described by <code>boundSignature</code>.
598          *
599          * @param boundSignature the additional bound to add to the list of
600          * collected bounds
601          */

602         private void addBound(String JavaDoc boundSignature) {
603             if (SignatureUtil.isJavaLangObject(boundSignature))
604                 return;
605             
606             boolean found= false;
607             for (ListIterator JavaDoc it= fBounds.listIterator(); it.hasNext();) {
608                 String JavaDoc old= (String JavaDoc) it.next();
609                 if (isTrueSubtypeOf(boundSignature, old)) {
610                     if (!found) {
611                         it.set(boundSignature);
612                         found= true;
613                     } else {
614                         it.remove();
615                     }
616                 }
617             }
618             if (!found)
619                 fBounds.add(boundSignature);
620         }
621
622         /**
623          * Returns <code>true</code> if <code>subTypeSignature</code>
624          * describes a type which is a true sub type of the type described by
625          * <code>superTypeSignature</code>.
626          *
627          * @param subTypeSignature the potential subtype's signature
628          * @param superTypeSignature the potential supertype's signature
629          * @return <code>true</code> if the inheritance relationship holds
630          */

631         private boolean isTrueSubtypeOf(String JavaDoc subTypeSignature, String JavaDoc superTypeSignature) {
632             // try cheap test first
633
if (subTypeSignature.equals(superTypeSignature))
634                 return true;
635             
636             if (SignatureUtil.isJavaLangObject(subTypeSignature))
637                 return false; // Object has no super types
638

639             if (Signature.getTypeSignatureKind(subTypeSignature) != Signature.BASE_TYPE_SIGNATURE && SignatureUtil.isJavaLangObject(superTypeSignature))
640                 return true;
641             
642             IJavaProject project= fUnit.getJavaProject();
643             
644             try {
645                 
646                 if ((Signature.getTypeSignatureKind(subTypeSignature) & (Signature.TYPE_VARIABLE_SIGNATURE | Signature.CLASS_TYPE_SIGNATURE)) == 0)
647                     return false;
648                 IType subType= project.findType(SignatureUtil.stripSignatureToFQN(subTypeSignature));
649                 if (subType == null)
650                     return false;
651                 
652                 if ((Signature.getTypeSignatureKind(superTypeSignature) & (Signature.TYPE_VARIABLE_SIGNATURE | Signature.CLASS_TYPE_SIGNATURE)) == 0)
653                     return false;
654                 IType superType= project.findType(SignatureUtil.stripSignatureToFQN(superTypeSignature));
655                 if (superType == null)
656                     return false;
657                 
658                 ITypeHierarchy hierarchy= subType.newSupertypeHierarchy(null);
659                 IType[] types= hierarchy.getAllSupertypes(subType);
660                 
661                 for (int i= 0; i < types.length; i++)
662                     if (types[i].equals(superType))
663                         return true;
664             } catch (JavaModelException e) {
665                 // ignore and return false
666
}
667             
668             return false;
669         }
670         
671         /**
672          * Returns <code>true</code> if <code>signature</code> is a concrete type signature,
673          * <code>false</code> if it is a type variable.
674          *
675          * @param signature the signature to check
676          * @param context the context inside which to resolve the type
677          * @throws JavaModelException if finding the type fails
678          */

679         private boolean isConcreteType(String JavaDoc signature, IType context) throws JavaModelException {
680             // Inexpensive check for the variable type first
681
if (Signature.TYPE_VARIABLE_SIGNATURE == Signature.getTypeSignatureKind(signature))
682                 return false;
683             
684             // try and resolve otherwise
685
if (context.isBinary()) {
686                 return fUnit.getJavaProject().findType(SignatureUtil.stripSignatureToFQN(signature)) != null;
687             } else {
688                 return context.resolveType(SignatureUtil.stripSignatureToFQN(signature)) != null;
689             }
690         }
691     }
692     
693     private ICompilationUnit fUnit;
694
695     private List JavaDoc fLocalVariables= new ArrayList JavaDoc();
696     private List JavaDoc fFields= new ArrayList JavaDoc();
697     private Map JavaDoc fLocalTypes= new HashMap JavaDoc();
698
699     private boolean fError;
700
701     /**
702      * Creates a compilation unit completion.
703      *
704      * @param unit the compilation unit, may be <code>null</code>.
705      */

706     CompilationUnitCompletion(ICompilationUnit unit) {
707         reset(unit);
708         setIgnored(CompletionProposal.ANONYMOUS_CLASS_DECLARATION, true);
709         setIgnored(CompletionProposal.KEYWORD, true);
710         setIgnored(CompletionProposal.LABEL_REF, true);
711         setIgnored(CompletionProposal.METHOD_DECLARATION, true);
712         setIgnored(CompletionProposal.METHOD_NAME_REFERENCE, true);
713         setIgnored(CompletionProposal.METHOD_REF, true);
714         setIgnored(CompletionProposal.PACKAGE_REF, true);
715         setIgnored(CompletionProposal.POTENTIAL_METHOD_DECLARATION, true);
716         setIgnored(CompletionProposal.VARIABLE_DECLARATION, true);
717         setIgnored(CompletionProposal.TYPE_REF, true);
718     }
719     
720     /**
721      * Resets the completion requester.
722      *
723      * @param unit the compilation unit, may be <code>null</code>.
724      */

725     private void reset(ICompilationUnit unit) {
726         fUnit= unit;
727         fLocalVariables.clear();
728         fFields.clear();
729         fLocalTypes.clear();
730         
731         if (fUnit != null) {
732             try {
733                 IType[] cuTypes= fUnit.getAllTypes();
734                 for (int i= 0; i < cuTypes.length; i++) {
735                     String JavaDoc fqn= cuTypes[i].getFullyQualifiedName();
736                     String JavaDoc sig= Signature.createTypeSignature(fqn, true);
737                     fLocalTypes.put(sig, cuTypes[i].getElementName());
738                 }
739             } catch (JavaModelException e) {
740                 // ignore
741
}
742         }
743         fError= false;
744     }
745
746     /*
747      * @see org.eclipse.jdt.core.CompletionRequestor#accept(org.eclipse.jdt.core.CompletionProposal)
748      */

749     public void accept(CompletionProposal proposal) {
750         
751         String JavaDoc name= String.valueOf(proposal.getCompletion());
752         String JavaDoc signature= String.valueOf(proposal.getSignature());
753         
754         switch (proposal.getKind()) {
755             
756             case CompletionProposal.LOCAL_VARIABLE_REF:
757                 // collect local variables
758
fLocalVariables.add(new Variable(name, signature));
759                 break;
760             case CompletionProposal.FIELD_REF:
761                 // collect local variables
762
fFields.add(new Variable(name, signature));
763                 break;
764                 
765             default:
766                 break;
767         }
768     }
769     
770     /*
771      * @see org.eclipse.jdt.core.CompletionRequestor#completionFailure(org.eclipse.jdt.core.compiler.IProblem)
772      */

773     public void completionFailure(IProblem problem) {
774         fError= true;
775     }
776
777     /**
778      * Tests if the code completion process produced errors.
779      *
780      * @return <code>true</code> if there are errors, <code>false</code>
781      * otherwise
782      */

783     public boolean hasErrors() {
784         return fError;
785     }
786
787     /**
788      * Returns all local variable names.
789      *
790      * @return all local variable names
791      */

792     public String JavaDoc[] getLocalVariableNames() {
793         String JavaDoc[] names= new String JavaDoc[fLocalVariables.size()];
794         int i= 0;
795         for (ListIterator JavaDoc iterator= fLocalVariables.listIterator(fLocalVariables.size()); iterator.hasPrevious();) {
796             Variable localVariable= (Variable) iterator.previous();
797             names[i++]= localVariable.getName();
798         }
799         return names;
800     }
801     
802     /**
803      * Returns all field names.
804      *
805      * @return all field names
806      * @since 3.3
807      */

808     public String JavaDoc[] getFieldNames() {
809         String JavaDoc[] names= new String JavaDoc[fFields.size()];
810         int i= 0;
811         for (ListIterator JavaDoc iterator= fFields.listIterator(fFields.size()); iterator.hasPrevious();) {
812             Variable field= (Variable)iterator.previous();
813             names[i++]= field.getName();
814         }
815         return names;
816     }
817
818     /**
819      * Returns all local arrays in the order that they appear.
820      *
821      * @return all local arrays
822      */

823     public Variable[] findLocalArrays() {
824         List JavaDoc arrays= new ArrayList JavaDoc();
825
826         for (ListIterator JavaDoc iterator= fLocalVariables.listIterator(fLocalVariables.size()); iterator.hasPrevious();) {
827             Variable localVariable= (Variable) iterator.previous();
828
829             if (localVariable.isArray())
830                 arrays.add(localVariable);
831         }
832
833         return (Variable[]) arrays.toArray(new Variable[arrays.size()]);
834     }
835     
836     /**
837      * Returns all local variables implementing or extending
838      * <code>clazz</code> in the order that they appear.
839      *
840      * @param clazz the fully qualified type name of the class to match
841      * @return all local variables matching <code>clazz</code>
842      */

843     public Variable[] findLocalVariables(String JavaDoc clazz) {
844         List JavaDoc matches= new ArrayList JavaDoc();
845         
846         for (ListIterator JavaDoc iterator= fLocalVariables.listIterator(fLocalVariables.size()); iterator.hasPrevious();) {
847             Variable localVariable= (Variable) iterator.previous();
848             
849             if (localVariable.isSubtypeOf(clazz))
850                 matches.add(localVariable);
851         }
852         
853         return (Variable[]) matches.toArray(new Variable[matches.size()]);
854     }
855     
856     /**
857      * Returns all local variables implementing or extending
858      * <code>clazz</code> in the order that they appear.
859      *
860      * @param clazz the fully qualified type name of the class to match
861      * @return all local variables matching <code>clazz</code>
862      */

863     public Variable[] findFieldVariables(String JavaDoc clazz) {
864         List JavaDoc matches= new ArrayList JavaDoc();
865         
866         for (ListIterator JavaDoc iterator= fFields.listIterator(fFields.size()); iterator.hasPrevious();) {
867             Variable localVariable= (Variable)iterator.previous();
868             
869             if (localVariable.isSubtypeOf(clazz))
870                 matches.add(localVariable);
871         }
872         
873         return (Variable[]) matches.toArray(new Variable[matches.size()]);
874     }
875
876     /**
877      * Returns all local variables implementing <code>java.lang.Iterable</code>
878      * <em>and</em> all local arrays, in the order that they appear. That is,
879      * the returned variables can be used within the <code>foreach</code>
880      * language construct.
881      *
882      * @return all local <code>Iterable</code>s and arrays
883      */

884     public Variable[] findLocalIterables() {
885         List JavaDoc iterables= new ArrayList JavaDoc();
886
887         for (ListIterator JavaDoc iterator= fLocalVariables.listIterator(fLocalVariables.size()); iterator.hasPrevious();) {
888             Variable localVariable= (Variable) iterator.previous();
889
890             if (localVariable.isArray() || localVariable.isIterable())
891                 iterables.add(localVariable);
892         }
893
894         return (Variable[]) iterables.toArray(new Variable[iterables.size()]);
895     }
896
897 }
898
899
Popular Tags