KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > core > search > BasicSearchEngine


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 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.search;
12
13 import java.util.*;
14
15 import org.eclipse.core.resources.*;
16 import org.eclipse.core.runtime.*;
17
18 import org.eclipse.jdt.core.*;
19 import org.eclipse.jdt.core.compiler.CharOperation;
20 import org.eclipse.jdt.core.search.*;
21 import org.eclipse.jdt.internal.compiler.*;
22 import org.eclipse.jdt.internal.compiler.ast.*;
23 import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
24 import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
25 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
26 import org.eclipse.jdt.internal.compiler.lookup.*;
27 import org.eclipse.jdt.internal.compiler.parser.Parser;
28 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
29 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
30 import org.eclipse.jdt.internal.core.*;
31 import org.eclipse.jdt.internal.core.search.indexing.*;
32 import org.eclipse.jdt.internal.core.search.matching.*;
33 import org.eclipse.jdt.internal.core.util.Messages;
34 import org.eclipse.jdt.internal.core.util.Util;
35
36 /**
37  * Search basic engine. Public search engine (see {@link org.eclipse.jdt.core.search.SearchEngine}
38  * for detailed comment), now uses basic engine functionalities.
39  * Note that serch basic engine does not implement deprecated functionalities...
40  */

41 public class BasicSearchEngine {
42
43     /*
44      * A default parser to parse non-reconciled working copies
45      */

46     private Parser parser;
47     private CompilerOptions compilerOptions;
48         
49     /*
50      * A list of working copies that take precedence over their original
51      * compilation units.
52      */

53     private ICompilationUnit[] workingCopies;
54     
55     /*
56      * A working copy owner whose working copies will take precedent over
57      * their original compilation units.
58      */

59     private WorkingCopyOwner workingCopyOwner;
60
61     /**
62      * For tracing purpose.
63      */

64     public static boolean VERBOSE = false;
65
66     /*
67      * Creates a new search basic engine.
68      */

69     public BasicSearchEngine() {
70         // will use working copies of PRIMARY owner
71
}
72     
73     /**
74      * @see SearchEngine#SearchEngine(ICompilationUnit[]) for detailed comment.
75      */

76     public BasicSearchEngine(ICompilationUnit[] workingCopies) {
77         this.workingCopies = workingCopies;
78     }
79
80     char convertTypeKind(int typeDeclarationKind) {
81         switch(typeDeclarationKind) {
82             case TypeDeclaration.CLASS_DECL : return IIndexConstants.CLASS_SUFFIX;
83             case TypeDeclaration.INTERFACE_DECL : return IIndexConstants.INTERFACE_SUFFIX;
84             case TypeDeclaration.ENUM_DECL : return IIndexConstants.ENUM_SUFFIX;
85             case TypeDeclaration.ANNOTATION_TYPE_DECL : return IIndexConstants.ANNOTATION_TYPE_SUFFIX;
86             default : return IIndexConstants.TYPE_SUFFIX;
87         }
88     }
89     /**
90      * @see SearchEngine#SearchEngine(WorkingCopyOwner) for detailed comment.
91      */

92     public BasicSearchEngine(WorkingCopyOwner workingCopyOwner) {
93         this.workingCopyOwner = workingCopyOwner;
94     }
95
96     /**
97      * @see SearchEngine#createHierarchyScope(IType) for detailed comment.
98      */

99     public static IJavaSearchScope createHierarchyScope(IType type) throws JavaModelException {
100         return createHierarchyScope(type, DefaultWorkingCopyOwner.PRIMARY);
101     }
102     
103     /**
104      * @see SearchEngine#createHierarchyScope(IType,WorkingCopyOwner) for detailed comment.
105      */

106     public static IJavaSearchScope createHierarchyScope(IType type, WorkingCopyOwner owner) throws JavaModelException {
107         return new HierarchyScope(type, owner);
108     }
109
110     /**
111      * @see SearchEngine#createJavaSearchScope(IJavaElement[]) for detailed comment.
112      */

113     public static IJavaSearchScope createJavaSearchScope(IJavaElement[] elements) {
114         return createJavaSearchScope(elements, true);
115     }
116
117     /**
118      * @see SearchEngine#createJavaSearchScope(IJavaElement[], boolean) for detailed comment.
119      */

120     public static IJavaSearchScope createJavaSearchScope(IJavaElement[] elements, boolean includeReferencedProjects) {
121         int includeMask = IJavaSearchScope.SOURCES | IJavaSearchScope.APPLICATION_LIBRARIES | IJavaSearchScope.SYSTEM_LIBRARIES;
122         if (includeReferencedProjects) {
123             includeMask |= IJavaSearchScope.REFERENCED_PROJECTS;
124         }
125         return createJavaSearchScope(elements, includeMask);
126     }
127
128     /**
129      * @see SearchEngine#createJavaSearchScope(IJavaElement[], int) for detailed comment.
130      */

131     public static IJavaSearchScope createJavaSearchScope(IJavaElement[] elements, int includeMask) {
132         JavaSearchScope scope = new JavaSearchScope();
133         HashSet visitedProjects = new HashSet(2);
134         for (int i = 0, length = elements.length; i < length; i++) {
135             IJavaElement element = elements[i];
136             if (element != null) {
137                 try {
138                     if (element instanceof JavaProject) {
139                         scope.add((JavaProject)element, includeMask, visitedProjects);
140                     } else {
141                         scope.add(element);
142                     }
143                 } catch (JavaModelException e) {
144                     // ignore
145
}
146             }
147         }
148         return scope;
149     }
150
151     /**
152      * @see SearchEngine#createTypeNameMatch(IType, int) for detailed comment.
153      */

154     public static TypeNameMatch createTypeNameMatch(IType type, int modifiers) {
155         return new JavaSearchTypeNameMatch(type, modifiers);
156     }
157     
158     /**
159      * @see SearchEngine#createWorkspaceScope() for detailed comment.
160      */

161     public static IJavaSearchScope createWorkspaceScope() {
162         return JavaModelManager.getJavaModelManager().getWorkspaceScope();
163     }
164     
165     /**
166      * Searches for matches to a given query. Search queries can be created using helper
167      * methods (from a String pattern or a Java element) and encapsulate the description of what is
168      * being searched (for example, search method declarations in a case sensitive way).
169      *
170      * @param scope the search result has to be limited to the given scope
171      * @param requestor a callback object to which each match is reported
172      */

173     void findMatches(SearchPattern pattern, SearchParticipant[] participants, IJavaSearchScope scope, SearchRequestor requestor, IProgressMonitor monitor) throws CoreException {
174         if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException();
175         try {
176             if (VERBOSE) {
177                 Util.verbose("Searching for pattern: " + pattern.toString()); //$NON-NLS-1$
178
Util.verbose(scope.toString());
179             }
180             if (participants == null) {
181                 if (VERBOSE) Util.verbose("No participants => do nothing!"); //$NON-NLS-1$
182
return;
183             }
184     
185             /* initialize progress monitor */
186             int length = participants.length;
187             if (monitor != null)
188                 monitor.beginTask(Messages.engine_searching, 100 * length);
189             IndexManager indexManager = JavaModelManager.getJavaModelManager().getIndexManager();
190             requestor.beginReporting();
191             for (int i = 0; i < length; i++) {
192                 if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException();
193     
194                 SearchParticipant participant = participants[i];
195                 try {
196                     if (monitor != null) monitor.subTask(Messages.bind(Messages.engine_searching_indexing, new String JavaDoc[] {participant.getDescription()}));
197                     participant.beginSearching();
198                     requestor.enterParticipant(participant);
199                     PathCollector pathCollector = new PathCollector();
200                     indexManager.performConcurrentJob(
201                         new PatternSearchJob(pattern, participant, scope, pathCollector),
202                         IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH,
203                         monitor==null ? null : new SubProgressMonitor(monitor, 50));
204                     if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException();
205     
206                     // locate index matches if any (note that all search matches could have been issued during index querying)
207
if (monitor != null) monitor.subTask(Messages.bind(Messages.engine_searching_matching, new String JavaDoc[] {participant.getDescription()}));
208                     String JavaDoc[] indexMatchPaths = pathCollector.getPaths();
209                     if (indexMatchPaths != null) {
210                         pathCollector = null; // release
211
int indexMatchLength = indexMatchPaths.length;
212                         SearchDocument[] indexMatches = new SearchDocument[indexMatchLength];
213                         for (int j = 0; j < indexMatchLength; j++) {
214                             indexMatches[j] = participant.getDocument(indexMatchPaths[j]);
215                         }
216                         SearchDocument[] matches = MatchLocator.addWorkingCopies(pattern, indexMatches, getWorkingCopies(), participant);
217                         participant.locateMatches(matches, pattern, scope, requestor, monitor==null ? null : new SubProgressMonitor(monitor, 50));
218                     }
219                 } finally {
220                     requestor.exitParticipant(participant);
221                     participant.doneSearching();
222                 }
223             }
224         } finally {
225             requestor.endReporting();
226             if (monitor != null)
227                 monitor.done();
228         }
229     }
230     /**
231      * Returns a new default Java search participant.
232      *
233      * @return a new default Java search participant
234      * @since 3.0
235      */

236     public static SearchParticipant getDefaultSearchParticipant() {
237         return new JavaSearchParticipant();
238     }
239
240
241     /**
242      * @param matchRule
243      */

244     public static String JavaDoc getMatchRuleString(final int matchRule) {
245         if (matchRule == 0) {
246             return "R_EXACT_MATCH"; //$NON-NLS-1$
247
}
248         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
249         for (int i=1; i<=8; i++) {
250             int bit = matchRule & (1<<(i-1));
251             if (bit != 0 && buffer.length()>0) buffer.append(" | "); //$NON-NLS-1$
252
switch (bit) {
253                 case SearchPattern.R_PREFIX_MATCH:
254                     buffer.append("R_PREFIX_MATCH"); //$NON-NLS-1$
255
break;
256                 case SearchPattern.R_CASE_SENSITIVE:
257                     buffer.append("R_CASE_SENSITIVE"); //$NON-NLS-1$
258
break;
259                 case SearchPattern.R_EQUIVALENT_MATCH:
260                     buffer.append("R_EQUIVALENT_MATCH"); //$NON-NLS-1$
261
break;
262                 case SearchPattern.R_ERASURE_MATCH:
263                     buffer.append("R_ERASURE_MATCH"); //$NON-NLS-1$
264
break;
265                 case SearchPattern.R_FULL_MATCH:
266                     buffer.append("R_FULL_MATCH"); //$NON-NLS-1$
267
break;
268                 case SearchPattern.R_PATTERN_MATCH:
269                     buffer.append("R_PATTERN_MATCH"); //$NON-NLS-1$
270
break;
271                 case SearchPattern.R_REGEXP_MATCH:
272                     buffer.append("R_REGEXP_MATCH"); //$NON-NLS-1$
273
break;
274                 case SearchPattern.R_CAMELCASE_MATCH:
275                     buffer.append("R_CAMELCASE_MATCH"); //$NON-NLS-1$
276
break;
277             }
278         }
279         return buffer.toString();
280     }
281
282     /**
283      * Return kind of search corresponding to given value.
284      *
285      * @param searchFor
286      */

287     public static String JavaDoc getSearchForString(final int searchFor) {
288         switch (searchFor) {
289             case IJavaSearchConstants.TYPE:
290                 return ("TYPE"); //$NON-NLS-1$
291
case IJavaSearchConstants.METHOD:
292                 return ("METHOD"); //$NON-NLS-1$
293
case IJavaSearchConstants.PACKAGE:
294                 return ("PACKAGE"); //$NON-NLS-1$
295
case IJavaSearchConstants.CONSTRUCTOR:
296                 return ("CONSTRUCTOR"); //$NON-NLS-1$
297
case IJavaSearchConstants.FIELD:
298                 return ("FIELD"); //$NON-NLS-1$
299
case IJavaSearchConstants.CLASS:
300                 return ("CLASS"); //$NON-NLS-1$
301
case IJavaSearchConstants.INTERFACE:
302                 return ("INTERFACE"); //$NON-NLS-1$
303
case IJavaSearchConstants.ENUM:
304                 return ("ENUM"); //$NON-NLS-1$
305
case IJavaSearchConstants.ANNOTATION_TYPE:
306                 return ("ANNOTATION_TYPE"); //$NON-NLS-1$
307
case IJavaSearchConstants.CLASS_AND_ENUM:
308                 return ("CLASS_AND_ENUM"); //$NON-NLS-1$
309
case IJavaSearchConstants.CLASS_AND_INTERFACE:
310                 return ("CLASS_AND_INTERFACE"); //$NON-NLS-1$
311
case IJavaSearchConstants.INTERFACE_AND_ANNOTATION:
312                 return ("INTERFACE_AND_ANNOTATION"); //$NON-NLS-1$
313
}
314         return "UNKNOWN"; //$NON-NLS-1$
315
}
316
317     private Parser getParser() {
318         if (this.parser == null) {
319             this.compilerOptions = new CompilerOptions(JavaCore.getOptions());
320             ProblemReporter problemReporter =
321                 new ProblemReporter(
322                     DefaultErrorHandlingPolicies.proceedWithAllProblems(),
323                     this.compilerOptions,
324                     new DefaultProblemFactory());
325             this.parser = new Parser(problemReporter, true);
326         }
327         return this.parser;
328     }
329
330     /*
331      * Returns the list of working copies used by this search engine.
332      * Returns null if none.
333      */

334     private ICompilationUnit[] getWorkingCopies() {
335         ICompilationUnit[] copies;
336         if (this.workingCopies != null) {
337             if (this.workingCopyOwner == null) {
338                 copies = JavaModelManager.getJavaModelManager().getWorkingCopies(DefaultWorkingCopyOwner.PRIMARY, false/*don't add primary WCs a second time*/);
339                 if (copies == null) {
340                     copies = this.workingCopies;
341                 } else {
342                     HashMap pathToCUs = new HashMap();
343                     for (int i = 0, length = copies.length; i < length; i++) {
344                         ICompilationUnit unit = copies[i];
345                         pathToCUs.put(unit.getPath(), unit);
346                     }
347                     for (int i = 0, length = this.workingCopies.length; i < length; i++) {
348                         ICompilationUnit unit = this.workingCopies[i];
349                         pathToCUs.put(unit.getPath(), unit);
350                     }
351                     int length = pathToCUs.size();
352                     copies = new ICompilationUnit[length];
353                     pathToCUs.values().toArray(copies);
354                 }
355             } else {
356                 copies = this.workingCopies;
357             }
358         } else if (this.workingCopyOwner != null) {
359             copies = JavaModelManager.getJavaModelManager().getWorkingCopies(this.workingCopyOwner, true/*add primary WCs*/);
360         } else {
361             copies = JavaModelManager.getJavaModelManager().getWorkingCopies(DefaultWorkingCopyOwner.PRIMARY, false/*don't add primary WCs a second time*/);
362         }
363         if (copies == null) return null;
364         
365         // filter out primary working copies that are saved
366
ICompilationUnit[] result = null;
367         int length = copies.length;
368         int index = 0;
369         for (int i = 0; i < length; i++) {
370             CompilationUnit copy = (CompilationUnit)copies[i];
371             try {
372                 if (!copy.isPrimary()
373                         || copy.hasUnsavedChanges()
374                         || copy.hasResourceChanged()) {
375                     if (result == null) {
376                         result = new ICompilationUnit[length];
377                     }
378                     result[index++] = copy;
379                 }
380             } catch (JavaModelException e) {
381                 // copy doesn't exist: ignore
382
}
383         }
384         if (index != length && result != null) {
385             System.arraycopy(result, 0, result = new ICompilationUnit[index], 0, index);
386         }
387         return result;
388     }
389     
390     /*
391      * Returns the list of working copies used to do the search on the given Java element.
392      */

393     private ICompilationUnit[] getWorkingCopies(IJavaElement element) {
394         if (element instanceof IMember) {
395             ICompilationUnit cu = ((IMember)element).getCompilationUnit();
396             if (cu != null && cu.isWorkingCopy()) {
397                 ICompilationUnit[] copies = getWorkingCopies();
398                 int length = copies == null ? 0 : copies.length;
399                 if (length > 0) {
400                     ICompilationUnit[] newWorkingCopies = new ICompilationUnit[length+1];
401                     System.arraycopy(copies, 0, newWorkingCopies, 0, length);
402                     newWorkingCopies[length] = cu;
403                     return newWorkingCopies;
404                 }
405                 return new ICompilationUnit[] {cu};
406             }
407         }
408         return getWorkingCopies();
409     }
410
411     boolean match(char patternTypeSuffix, int modifiers) {
412         switch(patternTypeSuffix) {
413             case IIndexConstants.CLASS_SUFFIX :
414                 return (modifiers & (Flags.AccAnnotation | Flags.AccInterface | Flags.AccEnum)) == 0;
415             case IIndexConstants.CLASS_AND_INTERFACE_SUFFIX:
416                 return (modifiers & (Flags.AccAnnotation | Flags.AccEnum)) == 0;
417             case IIndexConstants.CLASS_AND_ENUM_SUFFIX:
418                 return (modifiers & (Flags.AccAnnotation | Flags.AccInterface)) == 0;
419             case IIndexConstants.INTERFACE_SUFFIX :
420                 return (modifiers & Flags.AccInterface) != 0;
421             case IIndexConstants.INTERFACE_AND_ANNOTATION_SUFFIX:
422                 return (modifiers & (Flags.AccInterface | Flags.AccAnnotation)) != 0;
423             case IIndexConstants.ENUM_SUFFIX :
424                 return (modifiers & Flags.AccEnum) != 0;
425             case IIndexConstants.ANNOTATION_TYPE_SUFFIX :
426                 return (modifiers & Flags.AccAnnotation) != 0;
427         }
428         return true;
429     }
430
431     boolean match(char patternTypeSuffix, char[] patternPkg, char[] patternTypeName, int matchRule, int typeKind, char[] pkg, char[] typeName) {
432         switch(patternTypeSuffix) {
433             case IIndexConstants.CLASS_SUFFIX :
434                 if (typeKind != TypeDeclaration.CLASS_DECL) return false;
435                 break;
436             case IIndexConstants.CLASS_AND_INTERFACE_SUFFIX:
437                 if (typeKind != TypeDeclaration.CLASS_DECL && typeKind != TypeDeclaration.INTERFACE_DECL) return false;
438                 break;
439             case IIndexConstants.CLASS_AND_ENUM_SUFFIX:
440                 if (typeKind != TypeDeclaration.CLASS_DECL && typeKind != TypeDeclaration.ENUM_DECL) return false;
441                 break;
442             case IIndexConstants.INTERFACE_SUFFIX :
443                 if (typeKind != TypeDeclaration.INTERFACE_DECL) return false;
444                 break;
445             case IIndexConstants.INTERFACE_AND_ANNOTATION_SUFFIX:
446                 if (typeKind != TypeDeclaration.INTERFACE_DECL && typeKind != TypeDeclaration.ANNOTATION_TYPE_DECL) return false;
447                 break;
448             case IIndexConstants.ENUM_SUFFIX :
449                 if (typeKind != TypeDeclaration.ENUM_DECL) return false;
450                 break;
451             case IIndexConstants.ANNOTATION_TYPE_SUFFIX :
452                 if (typeKind != TypeDeclaration.ANNOTATION_TYPE_DECL) return false;
453                 break;
454             case IIndexConstants.TYPE_SUFFIX : // nothing
455
}
456     
457         boolean isCaseSensitive = (matchRule & SearchPattern.R_CASE_SENSITIVE) != 0;
458         if (patternPkg != null && !CharOperation.equals(patternPkg, pkg, isCaseSensitive))
459                 return false;
460         
461         if (patternTypeName != null) {
462             boolean isCamelCase = (matchRule & SearchPattern.R_CAMELCASE_MATCH) != 0;
463             int matchMode = matchRule & JavaSearchPattern.MATCH_MODE_MASK;
464             if (!isCaseSensitive && !isCamelCase) {
465                 patternTypeName = CharOperation.toLowerCase(patternTypeName);
466             }
467             boolean matchFirstChar = !isCaseSensitive || patternTypeName[0] == typeName[0];
468             if (isCamelCase && matchFirstChar && CharOperation.camelCaseMatch(patternTypeName, typeName)) {
469                 return true;
470             }
471             switch(matchMode) {
472                 case SearchPattern.R_EXACT_MATCH :
473                     if (!isCamelCase) {
474                         return matchFirstChar && CharOperation.equals(patternTypeName, typeName, isCaseSensitive);
475                     }
476                     // fall through next case to match as prefix if camel case failed
477
case SearchPattern.R_PREFIX_MATCH :
478                     return matchFirstChar && CharOperation.prefixEquals(patternTypeName, typeName, isCaseSensitive);
479                 case SearchPattern.R_PATTERN_MATCH :
480                     return CharOperation.match(patternTypeName, typeName, isCaseSensitive);
481                 case SearchPattern.R_REGEXP_MATCH :
482                     // TODO (frederic) implement regular expression match
483
break;
484             }
485         }
486         return true;
487     
488     }
489     
490     /**
491      * Searches for matches of a given search pattern. Search patterns can be created using helper
492      * methods (from a String pattern or a Java element) and encapsulate the description of what is
493      * being searched (for example, search method declarations in a case sensitive way).
494      *
495      * @see SearchEngine#search(SearchPattern, SearchParticipant[], IJavaSearchScope, SearchRequestor, IProgressMonitor)
496      * for detailed comment
497      */

498     public void search(SearchPattern pattern, SearchParticipant[] participants, IJavaSearchScope scope, SearchRequestor requestor, IProgressMonitor monitor) throws CoreException {
499         if (VERBOSE) {
500             Util.verbose("BasicSearchEngine.search(SearchPattern, SearchParticipant[], IJavaSearchScope, SearchRequestor, IProgressMonitor)"); //$NON-NLS-1$
501
}
502         findMatches(pattern, participants, scope, requestor, monitor);
503     }
504
505     /**
506      * Searches for all secondary types in the given scope.
507      * The search can be selecting specific types (given a package or a type name
508      * prefix and match modes).
509      */

510     public void searchAllSecondaryTypeNames(
511             IPackageFragmentRoot[] sourceFolders,
512             final IRestrictedAccessTypeRequestor nameRequestor,
513             boolean waitForIndexes,
514             IProgressMonitor progressMonitor) throws JavaModelException {
515
516         if (VERBOSE) {
517             Util.verbose("BasicSearchEngine.searchAllSecondaryTypeNames(IPackageFragmentRoot[], IRestrictedAccessTypeRequestor, boolean, IProgressMonitor)"); //$NON-NLS-1$
518
StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(" - source folders: "); //$NON-NLS-1$
519
int length = sourceFolders.length;
520             for (int i=0; i<length; i++) {
521                 if (i==0) {
522                     buffer.append('[');
523                 } else {
524                     buffer.append(',');
525                 }
526                 buffer.append(sourceFolders[i].getElementName());
527             }
528             buffer.append("]\n - waitForIndexes: "); //$NON-NLS-1$
529
buffer.append(waitForIndexes);
530             Util.verbose(buffer.toString());
531         }
532
533         IndexManager indexManager = JavaModelManager.getJavaModelManager().getIndexManager();
534         final TypeDeclarationPattern pattern = new SecondaryTypeDeclarationPattern();
535
536         // Get working copy path(s). Store in a single string in case of only one to optimize comparison in requestor
537
final HashSet workingCopyPaths = new HashSet();
538         String JavaDoc workingCopyPath = null;
539         ICompilationUnit[] copies = getWorkingCopies();
540         final int copiesLength = copies == null ? 0 : copies.length;
541         if (copies != null) {
542             if (copiesLength == 1) {
543                 workingCopyPath = copies[0].getPath().toString();
544             } else {
545                 for (int i = 0; i < copiesLength; i++) {
546                     ICompilationUnit workingCopy = copies[i];
547                     workingCopyPaths.add(workingCopy.getPath().toString());
548                 }
549             }
550         }
551         final String JavaDoc singleWkcpPath = workingCopyPath;
552
553         // Index requestor
554
IndexQueryRequestor searchRequestor = new IndexQueryRequestor(){
555             public boolean acceptIndexMatch(String JavaDoc documentPath, SearchPattern indexRecord, SearchParticipant participant, AccessRuleSet access) {
556                 // Filter unexpected types
557
TypeDeclarationPattern record = (TypeDeclarationPattern)indexRecord;
558                 if (!record.secondary) {
559                     return true; // filter maint types
560
}
561                 if (record.enclosingTypeNames == IIndexConstants.ONE_ZERO_CHAR) {
562                     return true; // filter out local and anonymous classes
563
}
564                 switch (copiesLength) {
565                     case 0:
566                         break;
567                     case 1:
568                         if (singleWkcpPath.equals(documentPath)) {
569                             return true; // fliter out *the* working copy
570
}
571                         break;
572                     default:
573                         if (workingCopyPaths.contains(documentPath)) {
574                             return true; // filter out working copies
575
}
576                         break;
577                 }
578
579                 // Accept document path
580
AccessRestriction accessRestriction = null;
581                 if (access != null) {
582                     // Compute document relative path
583
int pkgLength = (record.pkg==null || record.pkg.length==0) ? 0 : record.pkg.length+1;
584                     int nameLength = record.simpleName==null ? 0 : record.simpleName.length;
585                     char[] path = new char[pkgLength+nameLength];
586                     int pos = 0;
587                     if (pkgLength > 0) {
588                         System.arraycopy(record.pkg, 0, path, pos, pkgLength-1);
589                         CharOperation.replace(path, '.', '/');
590                         path[pkgLength-1] = '/';
591                         pos += pkgLength;
592                     }
593                     if (nameLength > 0) {
594                         System.arraycopy(record.simpleName, 0, path, pos, nameLength);
595                         pos += nameLength;
596                     }
597                     // Update access restriction if path is not empty
598
if (pos > 0) {
599                         accessRestriction = access.getViolatedRestriction(path);
600                     }
601                 }
602                 nameRequestor.acceptType(record.modifiers, record.pkg, record.simpleName, record.enclosingTypeNames, documentPath, accessRestriction);
603                 return true;
604             }
605         };
606
607         // add type names from indexes
608
try {
609             if (progressMonitor != null) {
610                 progressMonitor.beginTask(Messages.engine_searching, 100);
611             }
612             indexManager.performConcurrentJob(
613                 new PatternSearchJob(
614                     pattern,
615                     getDefaultSearchParticipant(), // Java search only
616
createJavaSearchScope(sourceFolders),
617                     searchRequestor),
618                 waitForIndexes
619                     ? IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH
620                     : IJavaSearchConstants.FORCE_IMMEDIATE_SEARCH,
621                 progressMonitor == null ? null : new SubProgressMonitor(progressMonitor, 100));
622         } catch (OperationCanceledException oce) {
623             // do nothing
624
} finally {
625             if (progressMonitor != null) {
626                 progressMonitor.done();
627             }
628         }
629     }
630
631     /**
632      * Searches for all top-level types and member types in the given scope.
633      * The search can be selecting specific types (given a package or a type name
634      * prefix and match modes).
635      *
636      * @see SearchEngine#searchAllTypeNames(char[], int, char[], int, int, IJavaSearchScope, TypeNameRequestor, int, IProgressMonitor)
637      * for detailed comment
638      */

639     public void searchAllTypeNames(
640         final char[] packageName,
641         final int packageMatchRule,
642         final char[] typeName,
643         final int typeMatchRule,
644         int searchFor,
645         IJavaSearchScope scope,
646         final IRestrictedAccessTypeRequestor nameRequestor,
647         int waitingPolicy,
648         IProgressMonitor progressMonitor) throws JavaModelException {
649
650         if (VERBOSE) {
651             Util.verbose("BasicSearchEngine.searchAllTypeNames(char[], char[], int, int, IJavaSearchScope, IRestrictedAccessTypeRequestor, int, IProgressMonitor)"); //$NON-NLS-1$
652
Util.verbose(" - package name: "+(packageName==null?"null":new String JavaDoc(packageName))); //$NON-NLS-1$ //$NON-NLS-2$
653
Util.verbose(" - match rule: "+getMatchRuleString(packageMatchRule)); //$NON-NLS-1$
654
Util.verbose(" - type name: "+(typeName==null?"null":new String JavaDoc(typeName))); //$NON-NLS-1$ //$NON-NLS-2$
655
Util.verbose(" - match rule: "+getMatchRuleString(typeMatchRule)); //$NON-NLS-1$
656
Util.verbose(" - search for: "+searchFor); //$NON-NLS-1$
657
Util.verbose(" - scope: "+scope); //$NON-NLS-1$
658
}
659
660         // Create pattern
661
IndexManager indexManager = JavaModelManager.getJavaModelManager().getIndexManager();
662         final char typeSuffix;
663         switch(searchFor){
664             case IJavaSearchConstants.CLASS :
665                 typeSuffix = IIndexConstants.CLASS_SUFFIX;
666                 break;
667             case IJavaSearchConstants.CLASS_AND_INTERFACE :
668                 typeSuffix = IIndexConstants.CLASS_AND_INTERFACE_SUFFIX;
669                 break;
670             case IJavaSearchConstants.CLASS_AND_ENUM :
671                 typeSuffix = IIndexConstants.CLASS_AND_ENUM_SUFFIX;
672                 break;
673             case IJavaSearchConstants.INTERFACE :
674                 typeSuffix = IIndexConstants.INTERFACE_SUFFIX;
675                 break;
676             case IJavaSearchConstants.INTERFACE_AND_ANNOTATION :
677                 typeSuffix = IIndexConstants.INTERFACE_AND_ANNOTATION_SUFFIX;
678                 break;
679             case IJavaSearchConstants.ENUM :
680                 typeSuffix = IIndexConstants.ENUM_SUFFIX;
681                 break;
682             case IJavaSearchConstants.ANNOTATION_TYPE :
683                 typeSuffix = IIndexConstants.ANNOTATION_TYPE_SUFFIX;
684                 break;
685             default :
686                 typeSuffix = IIndexConstants.TYPE_SUFFIX;
687                 break;
688         }
689         final TypeDeclarationPattern pattern = packageMatchRule == SearchPattern.R_EXACT_MATCH
690             ? new TypeDeclarationPattern(
691                 packageName,
692                 null,
693                 typeName,
694                 typeSuffix,
695                 typeMatchRule)
696             : new QualifiedTypeDeclarationPattern(
697                 packageName,
698                 packageMatchRule,
699                 typeName,
700                 typeSuffix,
701                 typeMatchRule);
702
703         // Get working copy path(s). Store in a single string in case of only one to optimize comparison in requestor
704
final HashSet workingCopyPaths = new HashSet();
705         String JavaDoc workingCopyPath = null;
706         ICompilationUnit[] copies = getWorkingCopies();
707         final int copiesLength = copies == null ? 0 : copies.length;
708         if (copies != null) {
709             if (copiesLength == 1) {
710                 workingCopyPath = copies[0].getPath().toString();
711             } else {
712                 for (int i = 0; i < copiesLength; i++) {
713                     ICompilationUnit workingCopy = copies[i];
714                     workingCopyPaths.add(workingCopy.getPath().toString());
715                 }
716             }
717         }
718         final String JavaDoc singleWkcpPath = workingCopyPath;
719
720         // Index requestor
721
IndexQueryRequestor searchRequestor = new IndexQueryRequestor(){
722             public boolean acceptIndexMatch(String JavaDoc documentPath, SearchPattern indexRecord, SearchParticipant participant, AccessRuleSet access) {
723                 // Filter unexpected types
724
TypeDeclarationPattern record = (TypeDeclarationPattern)indexRecord;
725                 if (record.enclosingTypeNames == IIndexConstants.ONE_ZERO_CHAR) {
726                     return true; // filter out local and anonymous classes
727
}
728                 switch (copiesLength) {
729                     case 0:
730                         break;
731                     case 1:
732                         if (singleWkcpPath.equals(documentPath)) {
733                             return true; // fliter out *the* working copy
734
}
735                         break;
736                     default:
737                         if (workingCopyPaths.contains(documentPath)) {
738                             return true; // filter out working copies
739
}
740                         break;
741                 }
742
743                 // Accept document path
744
AccessRestriction accessRestriction = null;
745                 if (access != null) {
746                     // Compute document relative path
747
int pkgLength = (record.pkg==null || record.pkg.length==0) ? 0 : record.pkg.length+1;
748                     int nameLength = record.simpleName==null ? 0 : record.simpleName.length;
749                     char[] path = new char[pkgLength+nameLength];
750                     int pos = 0;
751                     if (pkgLength > 0) {
752                         System.arraycopy(record.pkg, 0, path, pos, pkgLength-1);
753                         CharOperation.replace(path, '.', '/');
754                         path[pkgLength-1] = '/';
755                         pos += pkgLength;
756                     }
757                     if (nameLength > 0) {
758                         System.arraycopy(record.simpleName, 0, path, pos, nameLength);
759                         pos += nameLength;
760                     }
761                     // Update access restriction if path is not empty
762
if (pos > 0) {
763                         accessRestriction = access.getViolatedRestriction(path);
764                     }
765                 }
766                 if (match(record.typeSuffix, record.modifiers)) {
767                     nameRequestor.acceptType(record.modifiers, record.pkg, record.simpleName, record.enclosingTypeNames, documentPath, accessRestriction);
768                 }
769                 return true;
770             }
771         };
772     
773         try {
774             if (progressMonitor != null) {
775                 progressMonitor.beginTask(Messages.engine_searching, 100);
776             }
777             // add type names from indexes
778
indexManager.performConcurrentJob(
779                 new PatternSearchJob(
780                     pattern,
781                     getDefaultSearchParticipant(), // Java search only
782
scope,
783                     searchRequestor),
784                 waitingPolicy,
785                 progressMonitor == null ? null : new SubProgressMonitor(progressMonitor, 100));
786                 
787             // add type names from working copies
788
if (copies != null) {
789                 for (int i = 0; i < copiesLength; i++) {
790                     final ICompilationUnit workingCopy = copies[i];
791                     if (!scope.encloses(workingCopy)) continue;
792                     final String JavaDoc path = workingCopy.getPath().toString();
793                     if (workingCopy.isConsistent()) {
794                         IPackageDeclaration[] packageDeclarations = workingCopy.getPackageDeclarations();
795                         char[] packageDeclaration = packageDeclarations.length == 0 ? CharOperation.NO_CHAR : packageDeclarations[0].getElementName().toCharArray();
796                         IType[] allTypes = workingCopy.getAllTypes();
797                         for (int j = 0, allTypesLength = allTypes.length; j < allTypesLength; j++) {
798                             IType type = allTypes[j];
799                             IJavaElement parent = type.getParent();
800                             char[][] enclosingTypeNames;
801                             if (parent instanceof IType) {
802                                 char[] parentQualifiedName = ((IType)parent).getTypeQualifiedName('.').toCharArray();
803                                 enclosingTypeNames = CharOperation.splitOn('.', parentQualifiedName);
804                             } else {
805                                 enclosingTypeNames = CharOperation.NO_CHAR_CHAR;
806                             }
807                             char[] simpleName = type.getElementName().toCharArray();
808                             int kind;
809                             if (type.isEnum()) {
810                                 kind = TypeDeclaration.ENUM_DECL;
811                             } else if (type.isAnnotation()) {
812                                 kind = TypeDeclaration.ANNOTATION_TYPE_DECL;
813                             } else if (type.isClass()) {
814                                 kind = TypeDeclaration.CLASS_DECL;
815                             } else /*if (type.isInterface())*/ {
816                                 kind = TypeDeclaration.INTERFACE_DECL;
817                             }
818                             if (match(typeSuffix, packageName, typeName, typeMatchRule, kind, packageDeclaration, simpleName)) {
819                                 if (nameRequestor instanceof TypeNameMatchRequestorWrapper) {
820                                     ((TypeNameMatchRequestorWrapper)nameRequestor).requestor.acceptTypeNameMatch(new JavaSearchTypeNameMatch(type, type.getFlags()));
821                                 } else {
822                                     nameRequestor.acceptType(type.getFlags(), packageDeclaration, simpleName, enclosingTypeNames, path, null);
823                                 }
824                             }
825                         }
826                     } else {
827                         Parser basicParser = getParser();
828                         org.eclipse.jdt.internal.compiler.env.ICompilationUnit unit = (org.eclipse.jdt.internal.compiler.env.ICompilationUnit) workingCopy;
829                         CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.compilerOptions.maxProblemsPerUnit);
830                         CompilationUnitDeclaration parsedUnit = basicParser.dietParse(unit, compilationUnitResult);
831                         if (parsedUnit != null) {
832                             final char[] packageDeclaration = parsedUnit.currentPackage == null ? CharOperation.NO_CHAR : CharOperation.concatWith(parsedUnit.currentPackage.getImportName(), '.');
833                             class AllTypeDeclarationsVisitor extends ASTVisitor {
834                                 public boolean visit(TypeDeclaration typeDeclaration, BlockScope blockScope) {
835                                     return false; // no local/anonymous type
836
}
837                                 public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope compilationUnitScope) {
838                                     if (match(typeSuffix, packageName, typeName, typeMatchRule, TypeDeclaration.kind(typeDeclaration.modifiers), packageDeclaration, typeDeclaration.name)) {
839                                         if (nameRequestor instanceof TypeNameMatchRequestorWrapper) {
840                                             IType type = workingCopy.getType(new String JavaDoc(typeName));
841                                             ((TypeNameMatchRequestorWrapper)nameRequestor).requestor.acceptTypeNameMatch(new JavaSearchTypeNameMatch(type, typeDeclaration.modifiers));
842                                         } else {
843                                             nameRequestor.acceptType(typeDeclaration.modifiers, packageDeclaration, typeDeclaration.name, CharOperation.NO_CHAR_CHAR, path, null);
844                                         }
845                                     }
846                                     return true;
847                                 }
848                                 public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope classScope) {
849                                     if (match(typeSuffix, packageName, typeName, typeMatchRule, TypeDeclaration.kind(memberTypeDeclaration.modifiers), packageDeclaration, memberTypeDeclaration.name)) {
850                                         // compute encloising type names
851
TypeDeclaration enclosing = memberTypeDeclaration.enclosingType;
852                                         char[][] enclosingTypeNames = CharOperation.NO_CHAR_CHAR;
853                                         while (enclosing != null) {
854                                             enclosingTypeNames = CharOperation.arrayConcat(new char[][] {enclosing.name}, enclosingTypeNames);
855                                             if ((enclosing.bits & ASTNode.IsMemberType) != 0) {
856                                                 enclosing = enclosing.enclosingType;
857                                             } else {
858                                                 enclosing = null;
859                                             }
860                                         }
861                                         // report
862
if (nameRequestor instanceof TypeNameMatchRequestorWrapper) {
863                                             IType type = workingCopy.getType(new String JavaDoc(enclosingTypeNames[0]));
864                                             for (int j=1, l=enclosingTypeNames.length; j<l; j++) {
865                                                 type = type.getType(new String JavaDoc(enclosingTypeNames[j]));
866                                             }
867                                             ((TypeNameMatchRequestorWrapper)nameRequestor).requestor.acceptTypeNameMatch(new JavaSearchTypeNameMatch(type, 0));
868                                         } else {
869                                             nameRequestor.acceptType(memberTypeDeclaration.modifiers, packageDeclaration, memberTypeDeclaration.name, enclosingTypeNames, path, null);
870                                         }
871                                     }
872                                     return true;
873                                 }
874                             }
875                             parsedUnit.traverse(new AllTypeDeclarationsVisitor(), parsedUnit.scope);
876                         }
877                     }
878                 }
879             }
880         } finally {
881             if (progressMonitor != null) {
882                 progressMonitor.done();
883             }
884         }
885     }
886
887     /**
888      * Searches for all top-level types and member types in the given scope using a case sensitive exact match
889      * with the given qualified names and type names.
890      *
891      * @see SearchEngine#searchAllTypeNames(char[][], char[][], IJavaSearchScope, TypeNameRequestor, int, IProgressMonitor)
892      * for detailed comment
893      */

894     public void searchAllTypeNames(
895         final char[][] qualifications,
896         final char[][] typeNames,
897         final int matchRule,
898         int searchFor,
899         IJavaSearchScope scope,
900         final IRestrictedAccessTypeRequestor nameRequestor,
901         int waitingPolicy,
902         IProgressMonitor progressMonitor) throws JavaModelException {
903
904         if (VERBOSE) {
905             Util.verbose("BasicSearchEngine.searchAllTypeNames(char[][], char[][], int, int, IJavaSearchScope, IRestrictedAccessTypeRequestor, int, IProgressMonitor)"); //$NON-NLS-1$
906
Util.verbose(" - package name: "+(qualifications==null?"null":new String JavaDoc(CharOperation.concatWith(qualifications, ',')))); //$NON-NLS-1$ //$NON-NLS-2$
907
Util.verbose(" - type name: "+(typeNames==null?"null":new String JavaDoc(CharOperation.concatWith(typeNames, ',')))); //$NON-NLS-1$ //$NON-NLS-2$
908
Util.verbose(" - match rule: "+matchRule); //$NON-NLS-1$
909
Util.verbose(" - search for: "+searchFor); //$NON-NLS-1$
910
Util.verbose(" - scope: "+scope); //$NON-NLS-1$
911
}
912         IndexManager indexManager = JavaModelManager.getJavaModelManager().getIndexManager();
913
914         final char typeSuffix;
915         switch(searchFor){
916             case IJavaSearchConstants.CLASS :
917                 typeSuffix = IIndexConstants.CLASS_SUFFIX;
918                 break;
919             case IJavaSearchConstants.CLASS_AND_INTERFACE :
920                 typeSuffix = IIndexConstants.CLASS_AND_INTERFACE_SUFFIX;
921                 break;
922             case IJavaSearchConstants.CLASS_AND_ENUM :
923                 typeSuffix = IIndexConstants.CLASS_AND_ENUM_SUFFIX;
924                 break;
925             case IJavaSearchConstants.INTERFACE :
926                 typeSuffix = IIndexConstants.INTERFACE_SUFFIX;
927                 break;
928             case IJavaSearchConstants.INTERFACE_AND_ANNOTATION :
929                 typeSuffix = IIndexConstants.INTERFACE_AND_ANNOTATION_SUFFIX;
930                 break;
931             case IJavaSearchConstants.ENUM :
932                 typeSuffix = IIndexConstants.ENUM_SUFFIX;
933                 break;
934             case IJavaSearchConstants.ANNOTATION_TYPE :
935                 typeSuffix = IIndexConstants.ANNOTATION_TYPE_SUFFIX;
936                 break;
937             default :
938                 typeSuffix = IIndexConstants.TYPE_SUFFIX;
939                 break;
940         }
941         final MultiTypeDeclarationPattern pattern = new MultiTypeDeclarationPattern(qualifications, typeNames, typeSuffix, matchRule);
942
943         // Get working copy path(s). Store in a single string in case of only one to optimize comparison in requestor
944
final HashSet workingCopyPaths = new HashSet();
945         String JavaDoc workingCopyPath = null;
946         ICompilationUnit[] copies = getWorkingCopies();
947         final int copiesLength = copies == null ? 0 : copies.length;
948         if (copies != null) {
949             if (copiesLength == 1) {
950                 workingCopyPath = copies[0].getPath().toString();
951             } else {
952                 for (int i = 0; i < copiesLength; i++) {
953                     ICompilationUnit workingCopy = copies[i];
954                     workingCopyPaths.add(workingCopy.getPath().toString());
955                 }
956             }
957         }
958         final String JavaDoc singleWkcpPath = workingCopyPath;
959
960         // Index requestor
961
IndexQueryRequestor searchRequestor = new IndexQueryRequestor(){
962             public boolean acceptIndexMatch(String JavaDoc documentPath, SearchPattern indexRecord, SearchParticipant participant, AccessRuleSet access) {
963                 // Filter unexpected types
964
QualifiedTypeDeclarationPattern record = (QualifiedTypeDeclarationPattern) indexRecord;
965                 if (record.enclosingTypeNames == IIndexConstants.ONE_ZERO_CHAR) {
966                     return true; // filter out local and anonymous classes
967
}
968                 switch (copiesLength) {
969                     case 0:
970                         break;
971                     case 1:
972                         if (singleWkcpPath.equals(documentPath)) {
973                             return true; // fliter out *the* working copy
974
}
975                         break;
976                     default:
977                         if (workingCopyPaths.contains(documentPath)) {
978                             return true; // filter out working copies
979
}
980                         break;
981                 }
982
983                 // Accept document path
984
AccessRestriction accessRestriction = null;
985                 if (access != null) {
986                     // Compute document relative path
987
int qualificationLength = (record.qualification == null || record.qualification.length == 0) ? 0 : record.qualification.length + 1;
988                     int nameLength = record.simpleName == null ? 0 : record.simpleName.length;
989                     char[] path = new char[qualificationLength + nameLength];
990                     int pos = 0;
991                     if (qualificationLength > 0) {
992                         System.arraycopy(record.qualification, 0, path, pos, qualificationLength - 1);
993                         CharOperation.replace(path, '.', '/');
994                         path[qualificationLength-1] = '/';
995                         pos += qualificationLength;
996                     }
997                     if (nameLength > 0) {
998                         System.arraycopy(record.simpleName, 0, path, pos, nameLength);
999                         pos += nameLength;
1000                    }
1001                    // Update access restriction if path is not empty
1002
if (pos > 0) {
1003                        accessRestriction = access.getViolatedRestriction(path);
1004                    }
1005                }
1006                nameRequestor.acceptType(record.modifiers, record.pkg, record.simpleName, record.enclosingTypeNames, documentPath, accessRestriction);
1007                return true;
1008            }
1009        };
1010    
1011        try {
1012            if (progressMonitor != null) {
1013                progressMonitor.beginTask(Messages.engine_searching, 100);
1014            }
1015            // add type names from indexes
1016
indexManager.performConcurrentJob(
1017                new PatternSearchJob(
1018                    pattern,
1019                    getDefaultSearchParticipant(), // Java search only
1020
scope,
1021                    searchRequestor),
1022                waitingPolicy,
1023                progressMonitor == null ? null : new SubProgressMonitor(progressMonitor, 100));
1024                
1025            // add type names from working copies
1026
if (copies != null) {
1027                for (int i = 0, length = copies.length; i < length; i++) {
1028                    ICompilationUnit workingCopy = copies[i];
1029                    final String JavaDoc path = workingCopy.getPath().toString();
1030                    if (workingCopy.isConsistent()) {
1031                        IPackageDeclaration[] packageDeclarations = workingCopy.getPackageDeclarations();
1032                        char[] packageDeclaration = packageDeclarations.length == 0 ? CharOperation.NO_CHAR : packageDeclarations[0].getElementName().toCharArray();
1033                        IType[] allTypes = workingCopy.getAllTypes();
1034                        for (int j = 0, allTypesLength = allTypes.length; j < allTypesLength; j++) {
1035                            IType type = allTypes[j];
1036                            IJavaElement parent = type.getParent();
1037                            char[][] enclosingTypeNames;
1038                            char[] qualification = packageDeclaration;
1039                            if (parent instanceof IType) {
1040                                char[] parentQualifiedName = ((IType)parent).getTypeQualifiedName('.').toCharArray();
1041                                enclosingTypeNames = CharOperation.splitOn('.', parentQualifiedName);
1042                                qualification = CharOperation.concat(qualification, parentQualifiedName);
1043                            } else {
1044                                enclosingTypeNames = CharOperation.NO_CHAR_CHAR;
1045                            }
1046                            char[] simpleName = type.getElementName().toCharArray();
1047                            char suffix = IIndexConstants.TYPE_SUFFIX;
1048                            if (type.isClass()) {
1049                                suffix = IIndexConstants.CLASS_SUFFIX;
1050                            } else if (type.isInterface()) {
1051                                suffix = IIndexConstants.INTERFACE_SUFFIX;
1052                            } else if (type.isEnum()) {
1053                                suffix = IIndexConstants.ENUM_SUFFIX;
1054                            } else if (type.isAnnotation()) {
1055                                suffix = IIndexConstants.ANNOTATION_TYPE_SUFFIX;
1056                            }
1057                            if (pattern.matchesDecodedKey(new QualifiedTypeDeclarationPattern(qualification, simpleName, suffix, matchRule))) {
1058                                nameRequestor.acceptType(type.getFlags(), packageDeclaration, simpleName, enclosingTypeNames, path, null);
1059                            }
1060                        }
1061                    } else {
1062                        Parser basicParser = getParser();
1063                        org.eclipse.jdt.internal.compiler.env.ICompilationUnit unit = (org.eclipse.jdt.internal.compiler.env.ICompilationUnit) workingCopy;
1064                        CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.compilerOptions.maxProblemsPerUnit);
1065                        CompilationUnitDeclaration parsedUnit = basicParser.dietParse(unit, compilationUnitResult);
1066                        if (parsedUnit != null) {
1067                            final char[] packageDeclaration = parsedUnit.currentPackage == null
1068                                ? CharOperation.NO_CHAR
1069                                : CharOperation.concatWith(parsedUnit.currentPackage.getImportName(), '.');
1070                            class AllTypeDeclarationsVisitor extends ASTVisitor {
1071                                public boolean visit(TypeDeclaration typeDeclaration, BlockScope blockScope) {
1072                                    return false; // no local/anonymous type
1073
}
1074                                public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope compilationUnitScope) {
1075                                    SearchPattern decodedPattern =
1076                                        new QualifiedTypeDeclarationPattern(packageDeclaration, typeDeclaration.name, convertTypeKind(TypeDeclaration.kind(typeDeclaration.modifiers)), matchRule);
1077                                    if (pattern.matchesDecodedKey(decodedPattern)) {
1078                                        nameRequestor.acceptType(typeDeclaration.modifiers, packageDeclaration, typeDeclaration.name, CharOperation.NO_CHAR_CHAR, path, null);
1079                                    }
1080                                    return true;
1081                                }
1082                                public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope classScope) {
1083                                    // compute encloising type names
1084
char[] qualification = packageDeclaration;
1085                                    TypeDeclaration enclosing = memberTypeDeclaration.enclosingType;
1086                                    char[][] enclosingTypeNames = CharOperation.NO_CHAR_CHAR;
1087                                    while (enclosing != null) {
1088                                        qualification = CharOperation.concat(qualification, enclosing.name, '.');
1089                                        enclosingTypeNames = CharOperation.arrayConcat(new char[][] {enclosing.name}, enclosingTypeNames);
1090                                        if ((enclosing.bits & ASTNode.IsMemberType) != 0) {
1091                                            enclosing = enclosing.enclosingType;
1092                                        } else {
1093                                            enclosing = null;
1094                                        }
1095                                    }
1096                                    SearchPattern decodedPattern =
1097                                        new QualifiedTypeDeclarationPattern(qualification, memberTypeDeclaration.name, convertTypeKind(TypeDeclaration.kind(memberTypeDeclaration.modifiers)), matchRule);
1098                                    if (pattern.matchesDecodedKey(decodedPattern)) {
1099                                        nameRequestor.acceptType(memberTypeDeclaration.modifiers, packageDeclaration, memberTypeDeclaration.name, enclosingTypeNames, path, null);
1100                                    }
1101                                    return true;
1102                                }
1103                            }
1104                            parsedUnit.traverse(new AllTypeDeclarationsVisitor(), parsedUnit.scope);
1105                        }
1106                    }
1107                }
1108            }
1109        } finally {
1110            if (progressMonitor != null) {
1111                progressMonitor.done();
1112            }
1113        }
1114    }
1115    
1116    public void searchDeclarations(IJavaElement enclosingElement, SearchRequestor requestor, SearchPattern pattern, IProgressMonitor monitor) throws JavaModelException {
1117        if (VERBOSE) {
1118            Util.verbose(" - java element: "+enclosingElement); //$NON-NLS-1$
1119
}
1120        IJavaSearchScope scope = createJavaSearchScope(new IJavaElement[] {enclosingElement});
1121        IResource resource = enclosingElement.getResource();
1122        if (enclosingElement instanceof IMember) {
1123            IMember member = (IMember) enclosingElement;
1124            ICompilationUnit cu = member.getCompilationUnit();
1125            if (cu != null) {
1126                resource = cu.getResource();
1127            } else if (member.isBinary()) {
1128                // binary member resource cannot be used as this
1129
// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=148215
1130
resource = null;
1131            }
1132        }
1133        try {
1134            if (resource instanceof IFile) {
1135                try {
1136                    requestor.beginReporting();
1137                    if (VERBOSE) {
1138                        Util.verbose("Searching for " + pattern + " in " + resource.getFullPath()); //$NON-NLS-1$//$NON-NLS-2$
1139
}
1140                    SearchParticipant participant = getDefaultSearchParticipant();
1141                    SearchDocument[] documents = MatchLocator.addWorkingCopies(
1142                        pattern,
1143                        new SearchDocument[] {new JavaSearchDocument(enclosingElement.getPath().toString(), participant)},
1144                        getWorkingCopies(enclosingElement),
1145                        participant);
1146                    participant.locateMatches(
1147                        documents,
1148                        pattern,
1149                        scope,
1150                        requestor,
1151                        monitor);
1152                } finally {
1153                    requestor.endReporting();
1154                }
1155            } else {
1156                search(
1157                    pattern,
1158                    new SearchParticipant[] {getDefaultSearchParticipant()},
1159                    scope,
1160                    requestor,
1161                    monitor);
1162            }
1163        } catch (CoreException e) {
1164            if (e instanceof JavaModelException)
1165                throw (JavaModelException) e;
1166            throw new JavaModelException(e);
1167        }
1168    }
1169
1170    /**
1171     * Searches for all declarations of the fields accessed in the given element.
1172     * The element can be a compilation unit, a source type, or a source method.
1173     * Reports the field declarations using the given requestor.
1174     *
1175     * @see SearchEngine#searchDeclarationsOfAccessedFields(IJavaElement, SearchRequestor, IProgressMonitor)
1176     * for detailed comment
1177     */

1178    public void searchDeclarationsOfAccessedFields(IJavaElement enclosingElement, SearchRequestor requestor, IProgressMonitor monitor) throws JavaModelException {
1179        if (VERBOSE) {
1180            Util.verbose("BasicSearchEngine.searchDeclarationsOfAccessedFields(IJavaElement, SearchRequestor, SearchPattern, IProgressMonitor)"); //$NON-NLS-1$
1181
}
1182        SearchPattern pattern = new DeclarationOfAccessedFieldsPattern(enclosingElement);
1183        searchDeclarations(enclosingElement, requestor, pattern, monitor);
1184    }
1185    
1186    /**
1187     * Searches for all declarations of the types referenced in the given element.
1188     * The element can be a compilation unit, a source type, or a source method.
1189     * Reports the type declarations using the given requestor.
1190     *
1191     * @see SearchEngine#searchDeclarationsOfReferencedTypes(IJavaElement, SearchRequestor, IProgressMonitor)
1192     * for detailed comment
1193     */

1194    public void searchDeclarationsOfReferencedTypes(IJavaElement enclosingElement, SearchRequestor requestor, IProgressMonitor monitor) throws JavaModelException {
1195        if (VERBOSE) {
1196            Util.verbose("BasicSearchEngine.searchDeclarationsOfReferencedTypes(IJavaElement, SearchRequestor, SearchPattern, IProgressMonitor)"); //$NON-NLS-1$
1197
}
1198        SearchPattern pattern = new DeclarationOfReferencedTypesPattern(enclosingElement);
1199        searchDeclarations(enclosingElement, requestor, pattern, monitor);
1200    }
1201    
1202    /**
1203     * Searches for all declarations of the methods invoked in the given element.
1204     * The element can be a compilation unit, a source type, or a source method.
1205     * Reports the method declarations using the given requestor.
1206     *
1207     * @see SearchEngine#searchDeclarationsOfSentMessages(IJavaElement, SearchRequestor, IProgressMonitor)
1208     * for detailed comment
1209     */

1210    public void searchDeclarationsOfSentMessages(IJavaElement enclosingElement, SearchRequestor requestor, IProgressMonitor monitor) throws JavaModelException {
1211        if (VERBOSE) {
1212            Util.verbose("BasicSearchEngine.searchDeclarationsOfSentMessages(IJavaElement, SearchRequestor, SearchPattern, IProgressMonitor)"); //$NON-NLS-1$
1213
}
1214        SearchPattern pattern = new DeclarationOfReferencedMethodsPattern(enclosingElement);
1215        searchDeclarations(enclosingElement, requestor, pattern, monitor);
1216    }
1217}
1218
Popular Tags