KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > core > SearchableEnvironment


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.core;
12
13 import org.eclipse.core.runtime.IProgressMonitor;
14 import org.eclipse.core.runtime.OperationCanceledException;
15 import org.eclipse.jdt.core.*;
16 import org.eclipse.jdt.core.compiler.CharOperation;
17 import org.eclipse.jdt.core.search.*;
18 import org.eclipse.jdt.internal.codeassist.ISearchRequestor;
19 import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
20 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
21 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
22 import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
23 import org.eclipse.jdt.internal.compiler.env.ISourceType;
24 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
25 import org.eclipse.jdt.internal.core.search.BasicSearchEngine;
26 import org.eclipse.jdt.internal.core.search.IRestrictedAccessTypeRequestor;
27
28 /**
29  * This class provides a <code>SearchableBuilderEnvironment</code> for code assist which
30  * uses the Java model as a search tool.
31  */

32 public class SearchableEnvironment
33     implements INameEnvironment, IJavaSearchConstants {
34     
35     public NameLookup nameLookup;
36     protected ICompilationUnit unitToSkip;
37     protected org.eclipse.jdt.core.ICompilationUnit[] workingCopies;
38
39     protected JavaProject project;
40     protected IJavaSearchScope searchScope;
41     
42     protected boolean checkAccessRestrictions;
43
44     /**
45      * Creates a SearchableEnvironment on the given project
46      */

47     public SearchableEnvironment(JavaProject project, org.eclipse.jdt.core.ICompilationUnit[] workingCopies) throws JavaModelException {
48         this.project = project;
49         this.checkAccessRestrictions =
50             !JavaCore.IGNORE.equals(project.getOption(JavaCore.COMPILER_PB_FORBIDDEN_REFERENCE, true))
51             || !JavaCore.IGNORE.equals(project.getOption(JavaCore.COMPILER_PB_DISCOURAGED_REFERENCE, true));
52         this.workingCopies = workingCopies;
53         this.nameLookup = project.newNameLookup(workingCopies);
54
55         // Create search scope with visible entry on the project's classpath
56
if(this.checkAccessRestrictions) {
57             this.searchScope = BasicSearchEngine.createJavaSearchScope(new IJavaElement[] {project});
58         } else {
59             this.searchScope = BasicSearchEngine.createJavaSearchScope(this.nameLookup.packageFragmentRoots);
60         }
61     }
62
63     /**
64      * Creates a SearchableEnvironment on the given project
65      */

66     public SearchableEnvironment(JavaProject project, WorkingCopyOwner owner) throws JavaModelException {
67         this(project, owner == null ? null : JavaModelManager.getJavaModelManager().getWorkingCopies(owner, true/*add primary WCs*/));
68     }
69
70     private static int convertSearchFilterToModelFilter(int searchFilter) {
71         switch (searchFilter) {
72             case IJavaSearchConstants.CLASS:
73                 return NameLookup.ACCEPT_CLASSES;
74             case IJavaSearchConstants.INTERFACE:
75                 return NameLookup.ACCEPT_INTERFACES;
76             case IJavaSearchConstants.ENUM:
77                 return NameLookup.ACCEPT_ENUMS;
78             case IJavaSearchConstants.ANNOTATION_TYPE:
79                 return NameLookup.ACCEPT_ANNOTATIONS;
80             case IJavaSearchConstants.CLASS_AND_ENUM:
81                 return NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_ENUMS;
82             case IJavaSearchConstants.CLASS_AND_INTERFACE:
83                 return NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES;
84             default:
85                 return NameLookup.ACCEPT_ALL;
86         }
87     }
88     /**
89      * Returns the given type in the the given package if it exists,
90      * otherwise <code>null</code>.
91      */

92     protected NameEnvironmentAnswer find(String JavaDoc typeName, String JavaDoc packageName) {
93         if (packageName == null)
94             packageName = IPackageFragment.DEFAULT_PACKAGE_NAME;
95         NameLookup.Answer answer =
96             this.nameLookup.findType(
97                 typeName,
98                 packageName,
99                 false/*exact match*/,
100                 NameLookup.ACCEPT_ALL,
101                 this.checkAccessRestrictions);
102         if (answer != null) {
103             // construct name env answer
104
if (answer.type instanceof BinaryType) { // BinaryType
105
try {
106                     return new NameEnvironmentAnswer((IBinaryType) ((BinaryType) answer.type).getElementInfo(), answer.restriction);
107                 } catch (JavaModelException npe) {
108                     return null;
109                 }
110             } else { //SourceType
111
try {
112                     // retrieve the requested type
113
SourceTypeElementInfo sourceType = (SourceTypeElementInfo)((SourceType) answer.type).getElementInfo();
114                     ISourceType topLevelType = sourceType;
115                     while (topLevelType.getEnclosingType() != null) {
116                         topLevelType = topLevelType.getEnclosingType();
117                     }
118                     // find all siblings (other types declared in same unit, since may be used for name resolution)
119
IType[] types = sourceType.getHandle().getCompilationUnit().getTypes();
120                     ISourceType[] sourceTypes = new ISourceType[types.length];
121     
122                     // in the resulting collection, ensure the requested type is the first one
123
sourceTypes[0] = sourceType;
124                     int length = types.length;
125                     for (int i = 0, index = 1; i < length; i++) {
126                         ISourceType otherType =
127                             (ISourceType) ((JavaElement) types[i]).getElementInfo();
128                         if (!otherType.equals(topLevelType) && index < length) // check that the index is in bounds (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=62861)
129
sourceTypes[index++] = otherType;
130                     }
131                     return new NameEnvironmentAnswer(sourceTypes, answer.restriction);
132                 } catch (JavaModelException npe) {
133                     return null;
134                 }
135             }
136         }
137         return null;
138     }
139
140     /**
141      * Find the packages that start with the given prefix.
142      * A valid prefix is a qualified name separated by periods
143      * (ex. java.util).
144      * The packages found are passed to:
145      * ISearchRequestor.acceptPackage(char[][] packageName)
146      */

147     public void findPackages(char[] prefix, ISearchRequestor requestor) {
148         this.nameLookup.seekPackageFragments(
149             new String JavaDoc(prefix),
150             true,
151             new SearchableEnvironmentRequestor(requestor));
152     }
153
154     /**
155      * Find the top-level types that are defined
156      * in the current environment and whose simple name matches the given name.
157      *
158      * The types found are passed to one of the following methods (if additional
159      * information is known about the types):
160      * ISearchRequestor.acceptType(char[][] packageName, char[] typeName)
161      * ISearchRequestor.acceptClass(char[][] packageName, char[] typeName, int modifiers)
162      * ISearchRequestor.acceptInterface(char[][] packageName, char[] typeName, int modifiers)
163      *
164      * This method can not be used to find member types... member
165      * types are found relative to their enclosing type.
166      */

167     public void findExactTypes(char[] name, final boolean findMembers, int searchFor, final ISearchRequestor storage) {
168
169         try {
170             final String JavaDoc excludePath;
171             if (this.unitToSkip != null) {
172                 if (!(this.unitToSkip instanceof IJavaElement)) {
173                     // revert to model investigation
174
findExactTypes(
175                         new String JavaDoc(name),
176                         storage,
177                         convertSearchFilterToModelFilter(searchFor));
178                     return;
179                 }
180                 excludePath = ((IJavaElement) this.unitToSkip).getPath().toString();
181             } else {
182                 excludePath = null;
183             }
184
185             IProgressMonitor progressMonitor = new IProgressMonitor() {
186                 boolean isCanceled = false;
187                 public void beginTask(String JavaDoc n, int totalWork) {
188                     // implements interface method
189
}
190                 public void done() {
191                     // implements interface method
192
}
193                 public void internalWorked(double work) {
194                     // implements interface method
195
}
196                 public boolean isCanceled() {
197                     return isCanceled;
198                 }
199                 public void setCanceled(boolean value) {
200                     isCanceled = value;
201                 }
202                 public void setTaskName(String JavaDoc n) {
203                     // implements interface method
204
}
205                 public void subTask(String JavaDoc n) {
206                     // implements interface method
207
}
208                 public void worked(int work) {
209                     // implements interface method
210
}
211             };
212             IRestrictedAccessTypeRequestor typeRequestor = new IRestrictedAccessTypeRequestor() {
213                 public void acceptType(int modifiers, char[] packageName, char[] simpleTypeName, char[][] enclosingTypeNames, String JavaDoc path, AccessRestriction access) {
214                     if (excludePath != null && excludePath.equals(path))
215                         return;
216                     if (!findMembers && enclosingTypeNames != null && enclosingTypeNames.length > 0)
217                         return; // accept only top level types
218
storage.acceptType(packageName, simpleTypeName, enclosingTypeNames, modifiers, access);
219                 }
220             };
221             try {
222                 new BasicSearchEngine(this.workingCopies).searchAllTypeNames(
223                     null,
224                     SearchPattern.R_EXACT_MATCH,
225                     name,
226                     SearchPattern.R_EXACT_MATCH,
227                     searchFor,
228                     this.searchScope,
229                     typeRequestor,
230                     CANCEL_IF_NOT_READY_TO_SEARCH,
231                     progressMonitor);
232             } catch (OperationCanceledException e) {
233                 findExactTypes(
234                     new String JavaDoc(name),
235                     storage,
236                     convertSearchFilterToModelFilter(searchFor));
237             }
238         } catch (JavaModelException e) {
239             findExactTypes(
240                 new String JavaDoc(name),
241                 storage,
242                 convertSearchFilterToModelFilter(searchFor));
243         }
244     }
245     
246     /**
247      * Returns all types whose simple name matches with the given <code>name</code>.
248      */

249     private void findExactTypes(String JavaDoc name, ISearchRequestor storage, int type) {
250         SearchableEnvironmentRequestor requestor =
251             new SearchableEnvironmentRequestor(storage, this.unitToSkip, this.project, this.nameLookup);
252         this.nameLookup.seekTypes(name, null, false, type, requestor);
253     }
254     
255     /**
256      * @see org.eclipse.jdt.internal.compiler.env.INameEnvironment#findType(char[][])
257      */

258     public NameEnvironmentAnswer findType(char[][] compoundTypeName) {
259         if (compoundTypeName == null) return null;
260
261         int length = compoundTypeName.length;
262         if (length <= 1) {
263             if (length == 0) return null;
264             return find(new String JavaDoc(compoundTypeName[0]), null);
265         }
266
267         int lengthM1 = length - 1;
268         char[][] packageName = new char[lengthM1][];
269         System.arraycopy(compoundTypeName, 0, packageName, 0, lengthM1);
270
271         return find(
272             new String JavaDoc(compoundTypeName[lengthM1]),
273             CharOperation.toString(packageName));
274     }
275
276     /**
277      * @see org.eclipse.jdt.internal.compiler.env.INameEnvironment#findType(char[], char[][])
278      */

279     public NameEnvironmentAnswer findType(char[] name, char[][] packageName) {
280         if (name == null) return null;
281
282         return find(
283             new String JavaDoc(name),
284             packageName == null || packageName.length == 0 ? null : CharOperation.toString(packageName));
285     }
286
287     /**
288      * Find the top-level types that are defined
289      * in the current environment and whose name starts with the
290      * given prefix. The prefix is a qualified name separated by periods
291      * or a simple name (ex. java.util.V or V).
292      *
293      * The types found are passed to one of the following methods (if additional
294      * information is known about the types):
295      * ISearchRequestor.acceptType(char[][] packageName, char[] typeName)
296      * ISearchRequestor.acceptClass(char[][] packageName, char[] typeName, int modifiers)
297      * ISearchRequestor.acceptInterface(char[][] packageName, char[] typeName, int modifiers)
298      *
299      * This method can not be used to find member types... member
300      * types are found relative to their enclosing type.
301      */

302     public void findTypes(char[] prefix, final boolean findMembers, boolean camelCaseMatch, int searchFor, final ISearchRequestor storage) {
303
304         /*
305             if (true){
306                 findTypes(new String(prefix), storage, NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
307                 return;
308             }
309         */

310         try {
311             final String JavaDoc excludePath;
312             if (this.unitToSkip != null) {
313                 if (!(this.unitToSkip instanceof IJavaElement)) {
314                     // revert to model investigation
315
findTypes(
316                         new String JavaDoc(prefix),
317                         storage,
318                         convertSearchFilterToModelFilter(searchFor));
319                     return;
320                 }
321                 excludePath = ((IJavaElement) this.unitToSkip).getPath().toString();
322             } else {
323                 excludePath = null;
324             }
325             int lastDotIndex = CharOperation.lastIndexOf('.', prefix);
326             char[] qualification, simpleName;
327             if (lastDotIndex < 0) {
328                 qualification = null;
329                 if (camelCaseMatch) {
330                     simpleName = prefix;
331                 } else {
332                     simpleName = CharOperation.toLowerCase(prefix);
333                 }
334             } else {
335                 qualification = CharOperation.subarray(prefix, 0, lastDotIndex);
336                 if (camelCaseMatch) {
337                     simpleName = CharOperation.subarray(prefix, lastDotIndex + 1, prefix.length);
338                 } else {
339                     simpleName =
340                         CharOperation.toLowerCase(
341                             CharOperation.subarray(prefix, lastDotIndex + 1, prefix.length));
342                 }
343             }
344
345             IProgressMonitor progressMonitor = new IProgressMonitor() {
346                 boolean isCanceled = false;
347                 public void beginTask(String JavaDoc name, int totalWork) {
348                     // implements interface method
349
}
350                 public void done() {
351                     // implements interface method
352
}
353                 public void internalWorked(double work) {
354                     // implements interface method
355
}
356                 public boolean isCanceled() {
357                     return isCanceled;
358                 }
359                 public void setCanceled(boolean value) {
360                     isCanceled = value;
361                 }
362                 public void setTaskName(String JavaDoc name) {
363                     // implements interface method
364
}
365                 public void subTask(String JavaDoc name) {
366                     // implements interface method
367
}
368                 public void worked(int work) {
369                     // implements interface method
370
}
371             };
372             IRestrictedAccessTypeRequestor typeRequestor = new IRestrictedAccessTypeRequestor() {
373                 public void acceptType(int modifiers, char[] packageName, char[] simpleTypeName, char[][] enclosingTypeNames, String JavaDoc path, AccessRestriction access) {
374                     if (excludePath != null && excludePath.equals(path))
375                         return;
376                     if (!findMembers && enclosingTypeNames != null && enclosingTypeNames.length > 0)
377                         return; // accept only top level types
378
storage.acceptType(packageName, simpleTypeName, enclosingTypeNames, modifiers, access);
379                 }
380             };
381             try {
382                 int matchRule = SearchPattern.R_PREFIX_MATCH;
383                 if (camelCaseMatch) matchRule |= SearchPattern.R_CAMELCASE_MATCH;
384                 new BasicSearchEngine(this.workingCopies).searchAllTypeNames(
385                     qualification,
386                     SearchPattern.R_EXACT_MATCH,
387                     simpleName,
388                     matchRule, // not case sensitive
389
searchFor,
390                     this.searchScope,
391                     typeRequestor,
392                     CANCEL_IF_NOT_READY_TO_SEARCH,
393                     progressMonitor);
394             } catch (OperationCanceledException e) {
395                 findTypes(
396                     new String JavaDoc(prefix),
397                     storage,
398                     convertSearchFilterToModelFilter(searchFor));
399             }
400         } catch (JavaModelException e) {
401             findTypes(
402                 new String JavaDoc(prefix),
403                 storage,
404                 convertSearchFilterToModelFilter(searchFor));
405         }
406     }
407
408     /**
409      * Returns all types whose name starts with the given (qualified) <code>prefix</code>.
410      *
411      * If the <code>prefix</code> is unqualified, all types whose simple name matches
412      * the <code>prefix</code> are returned.
413      */

414     private void findTypes(String JavaDoc prefix, ISearchRequestor storage, int type) {
415         //TODO (david) should add camel case support
416
SearchableEnvironmentRequestor requestor =
417             new SearchableEnvironmentRequestor(storage, this.unitToSkip, this.project, this.nameLookup);
418         int index = prefix.lastIndexOf('.');
419         if (index == -1) {
420             this.nameLookup.seekTypes(prefix, null, true, type, requestor);
421         } else {
422             String JavaDoc packageName = prefix.substring(0, index);
423             JavaElementRequestor elementRequestor = new JavaElementRequestor();
424             this.nameLookup.seekPackageFragments(packageName, false, elementRequestor);
425             IPackageFragment[] fragments = elementRequestor.getPackageFragments();
426             if (fragments != null) {
427                 String JavaDoc className = prefix.substring(index + 1);
428                 for (int i = 0, length = fragments.length; i < length; i++)
429                     if (fragments[i] != null)
430                         this.nameLookup.seekTypes(className, fragments[i], true, type, requestor);
431             }
432         }
433     }
434
435     /**
436      * @see org.eclipse.jdt.internal.compiler.env.INameEnvironment#isPackage(char[][], char[])
437      */

438     public boolean isPackage(char[][] parentPackageName, char[] subPackageName) {
439         String JavaDoc[] pkgName;
440         if (parentPackageName == null)
441             pkgName = new String JavaDoc[] {new String JavaDoc(subPackageName)};
442         else {
443             int length = parentPackageName.length;
444             pkgName = new String JavaDoc[length+1];
445             for (int i = 0; i < length; i++)
446                 pkgName[i] = new String JavaDoc(parentPackageName[i]);
447             pkgName[length] = new String JavaDoc(subPackageName);
448         }
449         return this.nameLookup.isPackage(pkgName);
450     }
451
452     /**
453      * Returns a printable string for the array.
454      */

455     protected String JavaDoc toStringChar(char[] name) {
456         return "[" //$NON-NLS-1$
457
+ new String JavaDoc(name) + "]" ; //$NON-NLS-1$
458
}
459
460     /**
461      * Returns a printable string for the array.
462      */

463     protected String JavaDoc toStringCharChar(char[][] names) {
464         StringBuffer JavaDoc result = new StringBuffer JavaDoc();
465         for (int i = 0; i < names.length; i++) {
466             result.append(toStringChar(names[i]));
467         }
468         return result.toString();
469     }
470     
471     public void cleanup() {
472         // nothing to do
473
}
474 }
475
Popular Tags