KickJava   Java API By Example, From Geeks To Geeks.

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


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;
12
13 import java.io.File JavaDoc;
14 import java.util.*;
15
16 import org.eclipse.core.resources.*;
17 import org.eclipse.core.runtime.IPath;
18 import org.eclipse.core.runtime.IProgressMonitor;
19 import org.eclipse.jdt.core.IClasspathEntry;
20 import org.eclipse.jdt.core.ICompilationUnit;
21 import org.eclipse.jdt.core.IJavaElement;
22 import org.eclipse.jdt.core.IJavaProject;
23 import org.eclipse.jdt.core.IPackageFragment;
24 import org.eclipse.jdt.core.IPackageFragmentRoot;
25 import org.eclipse.jdt.core.IType;
26 import org.eclipse.jdt.core.JavaCore;
27 import org.eclipse.jdt.core.JavaModelException;
28 import org.eclipse.jdt.core.compiler.CharOperation;
29 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
30 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
31 import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
32 import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
33 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
34 import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
35 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
36 import org.eclipse.jdt.internal.core.util.HashtableOfArrayToObject;
37 import org.eclipse.jdt.internal.core.util.Messages;
38 import org.eclipse.jdt.internal.core.util.Util;
39
40 /**
41  * A <code>NameLookup</code> provides name resolution within a Java project.
42  * The name lookup facility uses the project's classpath to prioritize the
43  * order in which package fragments are searched when resolving a name.
44  *
45  * <p>Name lookup only returns a handle when the named element actually
46  * exists in the model; otherwise <code>null</code> is returned.
47  *
48  * <p>There are two logical sets of methods within this interface. Methods
49  * which start with <code>find*</code> are intended to be convenience methods for quickly
50  * finding an element within another element; for instance, for finding a class within a
51  * package. The other set of methods all begin with <code>seek*</code>. These methods
52  * do comprehensive searches of the <code>IJavaProject</code> returning hits
53  * in real time through an <code>IJavaElementRequestor</code>.
54  *
55  */

56 public class NameLookup implements SuffixConstants {
57     public static class Answer {
58         public IType type;
59         AccessRestriction restriction;
60         Answer(IType type, AccessRestriction restriction) {
61             this.type = type;
62             this.restriction = restriction;
63         }
64         public boolean ignoreIfBetter() {
65             return this.restriction != null && this.restriction.ignoreIfBetter();
66         }
67         /*
68          * Returns whether this answer is better than the other awswer.
69          * (accessible is better than discouraged, which is better than
70          * non-accessible)
71          */

72         public boolean isBetter(Answer otherAnswer) {
73             if (otherAnswer == null) return true;
74             if (this.restriction == null) return true;
75             return otherAnswer.restriction != null
76                 && this.restriction.getProblemId() < otherAnswer.restriction.getProblemId();
77         }
78     }
79
80     // TODO (jerome) suppress the accept flags (qualified name is sufficient to find a type)
81
/**
82      * Accept flag for specifying classes.
83      */

84     public static final int ACCEPT_CLASSES = ASTNode.Bit2;
85
86     /**
87      * Accept flag for specifying interfaces.
88      */

89     public static final int ACCEPT_INTERFACES = ASTNode.Bit3;
90     
91     /**
92      * Accept flag for specifying enums.
93      */

94     public static final int ACCEPT_ENUMS = ASTNode.Bit4;
95
96     /**
97      * Accept flag for specifying annotations.
98      */

99     public static final int ACCEPT_ANNOTATIONS = ASTNode.Bit5;
100     
101     /*
102      * Accept flag for all kinds of types
103      */

104     public static final int ACCEPT_ALL = ACCEPT_CLASSES | ACCEPT_INTERFACES | ACCEPT_ENUMS | ACCEPT_ANNOTATIONS;
105
106     public static boolean VERBOSE = false;
107     
108     private static final IType[] NO_TYPES = {};
109
110     /**
111      * The <code>IPackageFragmentRoot</code>'s associated
112      * with the classpath of this NameLookup facility's
113      * project.
114      */

115     protected IPackageFragmentRoot[] packageFragmentRoots;
116
117     /**
118      * Table that maps package names to lists of package fragment roots
119      * that contain such a package known by this name lookup facility.
120      * To allow > 1 package fragment with the same name, values are
121      * arrays of package fragment roots ordered as they appear on the
122      * classpath.
123      * Note if the list is of size 1, then the IPackageFragmentRoot object
124      * replaces the array.
125      */

126     protected HashtableOfArrayToObject packageFragments;
127     
128     /**
129      * Reverse map from root path to corresponding resolved CP entry
130      * (so as to be able to figure inclusion/exclusion rules)
131      */

132     protected Map rootToResolvedEntries;
133     
134     /**
135      * A map from package handles to a map from type name to an IType or an IType[].
136      * Allows working copies to take precedence over compilation units.
137      */

138     protected HashMap typesInWorkingCopies;
139
140     public long timeSpentInSeekTypesInSourcePackage = 0;
141     public long timeSpentInSeekTypesInBinaryPackage = 0;
142
143     public NameLookup(
144             IPackageFragmentRoot[] packageFragmentRoots,
145             HashtableOfArrayToObject packageFragments,
146             ICompilationUnit[] workingCopies,
147             Map rootToResolvedEntries) {
148         long start = -1;
149         if (VERBOSE) {
150             Util.verbose(" BUILDING NameLoopkup"); //$NON-NLS-1$
151
Util.verbose(" -> pkg roots size: " + (packageFragmentRoots == null ? 0 : packageFragmentRoots.length)); //$NON-NLS-1$
152
Util.verbose(" -> pkgs size: " + (packageFragments == null ? 0 : packageFragments.size())); //$NON-NLS-1$
153
Util.verbose(" -> working copy size: " + (workingCopies == null ? 0 : workingCopies.length)); //$NON-NLS-1$
154
start = System.currentTimeMillis();
155         }
156         this.packageFragmentRoots = packageFragmentRoots;
157         if (workingCopies == null) {
158             this.packageFragments = packageFragments;
159         } else {
160             // clone tables as we're adding packages from working copies
161
try {
162                 this.packageFragments = (HashtableOfArrayToObject) packageFragments.clone();
163             } catch (CloneNotSupportedException JavaDoc e1) {
164                 // ignore (implementation of HashtableOfArrayToObject supports cloning)
165
}
166             this.typesInWorkingCopies = new HashMap();
167             for (int i = 0, length = workingCopies.length; i < length; i++) {
168                 ICompilationUnit workingCopy = workingCopies[i];
169                 PackageFragment pkg = (PackageFragment) workingCopy.getParent();
170                 HashMap typeMap = (HashMap) this.typesInWorkingCopies.get(pkg);
171                 if (typeMap == null) {
172                     typeMap = new HashMap();
173                     this.typesInWorkingCopies.put(pkg, typeMap);
174                 }
175                 try {
176                     IType[] types = workingCopy.getTypes();
177                     int typeLength = types.length;
178                     if (typeLength == 0) {
179                         String JavaDoc typeName = Util.getNameWithoutJavaLikeExtension(workingCopy.getElementName());
180                         typeMap.put(typeName, NO_TYPES);
181                     } else {
182                         for (int j = 0; j < typeLength; j++) {
183                             IType type = types[j];
184                             String JavaDoc typeName = type.getElementName();
185                             Object JavaDoc existing = typeMap.get(typeName);
186                             if (existing == null) {
187                                 typeMap.put(typeName, type);
188                             } else if (existing instanceof IType) {
189                                 typeMap.put(typeName, new IType[] {(IType) existing, type});
190                             } else {
191                                 IType[] existingTypes = (IType[]) existing;
192                                 int existingTypeLength = existingTypes.length;
193                                 System.arraycopy(existingTypes, 0, existingTypes = new IType[existingTypeLength+1], 0, existingTypeLength);
194                                 existingTypes[existingTypeLength] = type;
195                                 typeMap.put(typeName, existingTypes);
196                             }
197                         }
198                     }
199                 } catch (JavaModelException e) {
200                     // working copy doesn't exist -> ignore
201
}
202                 
203                 // add root of package fragment to cache
204
IPackageFragmentRoot root = (IPackageFragmentRoot) pkg.getParent();
205                 String JavaDoc[] pkgName = pkg.names;
206                 Object JavaDoc existing = this.packageFragments.get(pkgName);
207                 if (existing == null || existing == JavaProjectElementInfo.NO_ROOTS) {
208                     this.packageFragments.put(pkgName, root);
209                     // ensure super packages (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=119161)
210
// are also in the map
211
JavaProjectElementInfo.addSuperPackageNames(pkgName, this.packageFragments);
212                 } else {
213                     if (existing instanceof PackageFragmentRoot) {
214                         if (!existing.equals(root))
215                             this.packageFragments.put(pkgName, new IPackageFragmentRoot[] {(PackageFragmentRoot) existing, root});
216                     } else {
217                         IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) existing;
218                         int rootLength = roots.length;
219                         boolean containsRoot = false;
220                         for (int j = 0; j < rootLength; j++) {
221                             if (roots[j].equals(root)) {
222                                 containsRoot = true;
223                                 break;
224                             }
225                         }
226                         if (containsRoot) {
227                             System.arraycopy(roots, 0, roots = new IPackageFragmentRoot[rootLength+1], 0, rootLength);
228                             roots[rootLength] = root;
229                             this.packageFragments.put(pkgName, roots);
230                         }
231                     }
232                 }
233             }
234         }
235         
236         this.rootToResolvedEntries = rootToResolvedEntries;
237         if (VERBOSE) {
238             Util.verbose(" -> spent: " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
239
}
240     }
241
242     /**
243      * Returns true if:<ul>
244      * <li>the given type is an existing class and the flag's <code>ACCEPT_CLASSES</code>
245      * bit is on
246      * <li>the given type is an existing interface and the <code>ACCEPT_INTERFACES</code>
247      * bit is on
248      * <li>neither the <code>ACCEPT_CLASSES</code> or <code>ACCEPT_INTERFACES</code>
249      * bit is on
250      * </ul>
251      * Otherwise, false is returned.
252      */

253     protected boolean acceptType(IType type, int acceptFlags, boolean isSourceType) {
254         if (acceptFlags == 0 || acceptFlags == ACCEPT_ALL)
255             return true; // no flags or all flags, always accepted
256
try {
257             int kind = isSourceType
258                     ? TypeDeclaration.kind(((SourceTypeElementInfo) ((SourceType) type).getElementInfo()).getModifiers())
259                     : TypeDeclaration.kind(((IBinaryType) ((BinaryType) type).getElementInfo()).getModifiers());
260             switch (kind) {
261                 case TypeDeclaration.CLASS_DECL :
262                     return (acceptFlags & ACCEPT_CLASSES) != 0;
263                 case TypeDeclaration.INTERFACE_DECL :
264                     return (acceptFlags & ACCEPT_INTERFACES) != 0;
265                 case TypeDeclaration.ENUM_DECL :
266                     return (acceptFlags & ACCEPT_ENUMS) != 0;
267                 default:
268                     //case IGenericType.ANNOTATION_TYPE :
269
return (acceptFlags & ACCEPT_ANNOTATIONS) != 0;
270             }
271         } catch (JavaModelException npe) {
272             return false; // the class is not present, do not accept.
273
}
274     }
275
276     /**
277      * Finds every type in the project whose simple name matches
278      * the prefix, informing the requestor of each hit. The requestor
279      * is polled for cancellation at regular intervals.
280      *
281      * <p>The <code>partialMatch</code> argument indicates partial matches
282      * should be considered.
283      */

284     private void findAllTypes(String JavaDoc prefix, boolean partialMatch, int acceptFlags, IJavaElementRequestor requestor) {
285         int count= this.packageFragmentRoots.length;
286         for (int i= 0; i < count; i++) {
287             if (requestor.isCanceled())
288                 return;
289             IPackageFragmentRoot root= this.packageFragmentRoots[i];
290             IJavaElement[] packages= null;
291             try {
292                 packages= root.getChildren();
293             } catch (JavaModelException npe) {
294                 continue; // the root is not present, continue;
295
}
296             if (packages != null) {
297                 for (int j= 0, packageCount= packages.length; j < packageCount; j++) {
298                     if (requestor.isCanceled())
299                         return;
300                     seekTypes(prefix, (IPackageFragment) packages[j], partialMatch, acceptFlags, requestor);
301                 }
302             }
303         }
304     }
305
306     /**
307      * Returns the <code>ICompilationUnit</code> which defines the type
308      * named <code>qualifiedTypeName</code>, or <code>null</code> if
309      * none exists. The domain of the search is bounded by the classpath
310      * of the <code>IJavaProject</code> this <code>NameLookup</code> was
311      * obtained from.
312      * <p>
313      * The name must be fully qualified (eg "java.lang.Object", "java.util.Hashtable$Entry")
314      */

315     public ICompilationUnit findCompilationUnit(String JavaDoc qualifiedTypeName) {
316         String JavaDoc[] pkgName = CharOperation.NO_STRINGS;
317         String JavaDoc cuName = qualifiedTypeName;
318
319         int index= qualifiedTypeName.lastIndexOf('.');
320         if (index != -1) {
321             pkgName= Util.splitOn('.', qualifiedTypeName, 0, index);
322             cuName= qualifiedTypeName.substring(index + 1);
323         }
324         index= cuName.indexOf('$');
325         if (index != -1) {
326             cuName= cuName.substring(0, index);
327         }
328         Object JavaDoc value = this.packageFragments.get(pkgName);
329         if (value != null) {
330             if (value instanceof PackageFragmentRoot) {
331                 return findCompilationUnit(pkgName, cuName, (PackageFragmentRoot) value);
332             } else {
333                 IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) value;
334                 for (int i= 0; i < roots.length; i++) {
335                     PackageFragmentRoot root= (PackageFragmentRoot) roots[i];
336                     ICompilationUnit cu = findCompilationUnit(pkgName, cuName, root);
337                     if (cu != null)
338                         return cu;
339                 }
340             }
341         }
342         return null;
343     }
344     
345     private ICompilationUnit findCompilationUnit(String JavaDoc[] pkgName, String JavaDoc cuName, PackageFragmentRoot root) {
346         if (!root.isArchive()) {
347             IPackageFragment pkg = root.getPackageFragment(pkgName);
348             try {
349                 ICompilationUnit[] cus = pkg.getCompilationUnits();
350                 for (int j = 0, length = cus.length; j < length; j++) {
351                     ICompilationUnit cu = cus[j];
352                     if (Util.equalsIgnoreJavaLikeExtension(cu.getElementName(), cuName))
353                         return cu;
354                 }
355             } catch (JavaModelException e) {
356                 // pkg does not exist
357
// -> try next package
358
}
359         }
360         return null;
361 }
362     
363     /**
364      * Returns the package fragment whose path matches the given
365      * (absolute) path, or <code>null</code> if none exist. The domain of
366      * the search is bounded by the classpath of the <code>IJavaProject</code>
367      * this <code>NameLookup</code> was obtained from.
368      * The path can be:
369      * - internal to the workbench: "/Project/src"
370      * - external to the workbench: "c:/jdk/classes.zip/java/lang"
371      */

372     public IPackageFragment findPackageFragment(IPath path) {
373         if (!path.isAbsolute()) {
374             throw new IllegalArgumentException JavaDoc(Messages.path_mustBeAbsolute);
375         }
376 /*
377  * TODO (jerome) this code should rather use the package fragment map to find the candidate package, then
378  * check if the respective enclosing root maps to the one on this given IPath.
379  */

380         IResource possibleFragment = ResourcesPlugin.getWorkspace().getRoot().findMember(path);
381         if (possibleFragment == null) {
382             //external jar
383
for (int i = 0; i < this.packageFragmentRoots.length; i++) {
384                 IPackageFragmentRoot root = this.packageFragmentRoots[i];
385                 if (!root.isExternal()) {
386                     continue;
387                 }
388                 IPath rootPath = root.getPath();
389                 int matchingCount = rootPath.matchingFirstSegments(path);
390                 if (matchingCount != 0) {
391                     String JavaDoc name = path.toOSString();
392                     // + 1 is for the File.separatorChar
393
name = name.substring(rootPath.toOSString().length() + 1, name.length());
394                     name = name.replace(File.separatorChar, '.');
395                     IJavaElement[] list = null;
396                     try {
397                         list = root.getChildren();
398                     } catch (JavaModelException npe) {
399                         continue; // the package fragment root is not present;
400
}
401                     int elementCount = list.length;
402                     for (int j = 0; j < elementCount; j++) {
403                         IPackageFragment packageFragment = (IPackageFragment) list[j];
404                         if (nameMatches(name, packageFragment, false)) {
405                             return packageFragment;
406                         }
407                     }
408                 }
409             }
410         } else {
411             IJavaElement fromFactory = JavaCore.create(possibleFragment);
412             if (fromFactory == null) {
413                 return null;
414             }
415             switch (fromFactory.getElementType()) {
416                 case IJavaElement.PACKAGE_FRAGMENT:
417                     return (IPackageFragment) fromFactory;
418                 case IJavaElement.JAVA_PROJECT:
419                     // default package in a default root
420
JavaProject project = (JavaProject) fromFactory;
421                     try {
422                         IClasspathEntry entry = project.getClasspathEntryFor(path);
423                         if (entry != null) {
424                             IPackageFragmentRoot root =
425                                 project.getPackageFragmentRoot(project.getResource());
426                             Object JavaDoc defaultPkgRoot = this.packageFragments.get(CharOperation.NO_STRINGS);
427                             if (defaultPkgRoot == null) {
428                                 return null;
429                             }
430                             if (defaultPkgRoot instanceof PackageFragmentRoot && defaultPkgRoot.equals(root))
431                                 return ((PackageFragmentRoot) root).getPackageFragment(CharOperation.NO_STRINGS);
432                             else {
433                                 IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) defaultPkgRoot;
434                                 for (int i = 0; i < roots.length; i++) {
435                                     if (roots[i].equals(root)) {
436                                         return ((PackageFragmentRoot) root).getPackageFragment(CharOperation.NO_STRINGS);
437                                     }
438                                 }
439                             }
440                         }
441                     } catch (JavaModelException e) {
442                         return null;
443                     }
444                     return null;
445                 case IJavaElement.PACKAGE_FRAGMENT_ROOT:
446                     return ((PackageFragmentRoot)fromFactory).getPackageFragment(CharOperation.NO_STRINGS);
447             }
448         }
449         return null;
450     }
451
452     /**
453      * Returns the package fragments whose name matches the given
454      * (qualified) name, or <code>null</code> if none exist.
455      *
456      * The name can be:
457      * <ul>
458      * <li>empty: ""</li>
459      * <li>qualified: "pack.pack1.pack2"</li>
460      * </ul>
461      * @param partialMatch partial name matches qualify when <code>true</code>,
462      * only exact name matches qualify when <code>false</code>
463      */

464     public IPackageFragment[] findPackageFragments(String JavaDoc name, boolean partialMatch) {
465         return findPackageFragments(name, partialMatch, false);
466     }
467
468     /**
469      * Returns the package fragments whose name matches the given
470      * (qualified) name or pattern, or <code>null</code> if none exist.
471      *
472      * The name can be:
473      * <ul>
474      * <li>empty: ""</li>
475      * <li>qualified: "pack.pack1.pack2"</li>
476      * <li>a pattern: "pack.*.util"</li>
477      * </ul>
478      * @param partialMatch partial name matches qualify when <code>true</code>,
479      * @param patternMatch <code>true</code> when the given name might be a pattern,
480      * <code>false</code> otherwise.
481      */

482     public IPackageFragment[] findPackageFragments(String JavaDoc name, boolean partialMatch, boolean patternMatch) {
483         boolean hasPatternChars = patternMatch && (name.indexOf('*') >= 0 || name.indexOf('?') >= 0);
484         if (partialMatch || hasPatternChars) {
485             String JavaDoc[] splittedName = Util.splitOn('.', name, 0, name.length());
486             IPackageFragment[] oneFragment = null;
487             ArrayList pkgs = null;
488             Object JavaDoc[][] keys = this.packageFragments.keyTable;
489             for (int i = 0, length = keys.length; i < length; i++) {
490                 String JavaDoc[] pkgName = (String JavaDoc[]) keys[i];
491                 if (pkgName != null) {
492                     boolean match = hasPatternChars
493                         ? Util.matchesWithIgnoreCase(pkgName, name)
494                         : Util.startsWithIgnoreCase(pkgName, splittedName, partialMatch);
495                     if (match) {
496                         Object JavaDoc value = this.packageFragments.valueTable[i];
497                         if (value instanceof PackageFragmentRoot) {
498                             IPackageFragment pkg = ((PackageFragmentRoot) value).getPackageFragment(pkgName);
499                             if (oneFragment == null) {
500                                 oneFragment = new IPackageFragment[] {pkg};
501                             } else {
502                                 if (pkgs == null) {
503                                     pkgs = new ArrayList();
504                                     pkgs.add(oneFragment[0]);
505                                 }
506                                 pkgs.add(pkg);
507                             }
508                         } else {
509                             IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) value;
510                             for (int j = 0, length2 = roots.length; j < length2; j++) {
511                                 PackageFragmentRoot root = (PackageFragmentRoot) roots[j];
512                                 IPackageFragment pkg = root.getPackageFragment(pkgName);
513                                 if (oneFragment == null) {
514                                     oneFragment = new IPackageFragment[] {pkg};
515                                 } else {
516                                     if (pkgs == null) {
517                                         pkgs = new ArrayList();
518                                         pkgs.add(oneFragment[0]);
519                                     }
520                                     pkgs.add(pkg);
521                                 }
522                             }
523                         }
524                     }
525                 }
526             }
527             if (pkgs == null) return oneFragment;
528             int resultLength = pkgs.size();
529             IPackageFragment[] result = new IPackageFragment[resultLength];
530             pkgs.toArray(result);
531             return result;
532         } else {
533             String JavaDoc[] splittedName = Util.splitOn('.', name, 0, name.length());
534             Object JavaDoc value = this.packageFragments.get(splittedName);
535             if (value == null)
536                 return null;
537             if (value instanceof PackageFragmentRoot) {
538                 return new IPackageFragment[] {((PackageFragmentRoot) value).getPackageFragment(splittedName)};
539             } else {
540                 IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) value;
541                 IPackageFragment[] result = new IPackageFragment[roots.length];
542                 for (int i= 0; i < roots.length; i++) {
543                     result[i] = ((PackageFragmentRoot) roots[i]).getPackageFragment(splittedName);
544                 }
545                 return result;
546             }
547         }
548     }
549
550     /*
551      * Find secondary type for a project.
552      */

553     private IType findSecondaryType(String JavaDoc packageName, String JavaDoc typeName, IJavaProject project, boolean waitForIndexes, IProgressMonitor monitor) {
554         if (JavaModelManager.VERBOSE) {
555             Util.verbose("NameLookup FIND SECONDARY TYPES:"); //$NON-NLS-1$
556
Util.verbose(" -> pkg name: " + packageName); //$NON-NLS-1$
557
Util.verbose(" -> type name: " + typeName); //$NON-NLS-1$
558
Util.verbose(" -> project: "+project.getElementName()); //$NON-NLS-1$
559
}
560         JavaModelManager manager = JavaModelManager.getJavaModelManager();
561         try {
562             IJavaProject javaProject = project;
563             Map secondaryTypePaths = manager.secondaryTypes(javaProject, waitForIndexes, monitor);
564             if (secondaryTypePaths.size() > 0) {
565                 Map types = (Map) secondaryTypePaths.get(packageName==null?"":packageName); //$NON-NLS-1$
566
if (types != null && types.size() > 0) {
567                     IType type = (IType) types.get(typeName);
568                     if (type != null) {
569                         if (JavaModelManager.VERBOSE) {
570                             Util.verbose(" -> type: " + type.getElementName()); //$NON-NLS-1$
571
}
572                         return type;
573                     }
574                 }
575             }
576         }
577         catch (JavaModelException jme) {
578             // give up
579
}
580         return null;
581     }
582
583     /**
584      * Find type considering secondary types but without waiting for indexes.
585      * It means that secondary types may be not found under certain circumstances...
586      * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=118789"
587      */

588     public Answer findType(String JavaDoc typeName, String JavaDoc packageName, boolean partialMatch, int acceptFlags, boolean checkRestrictions) {
589         return findType(typeName,
590             packageName,
591             partialMatch,
592             acceptFlags,
593             true/* consider secondary types */,
594             false/* do NOT wait for indexes */,
595             checkRestrictions,
596             null);
597     }
598
599     /**
600      * Find type. Considering secondary types and waiting for indexes depends on given corresponding parameters.
601      */

602     public Answer findType(
603             String JavaDoc typeName,
604             String JavaDoc packageName,
605             boolean partialMatch,
606             int acceptFlags,
607             boolean considerSecondaryTypes,
608             boolean waitForIndexes,
609             boolean checkRestrictions,
610             IProgressMonitor monitor) {
611         if (packageName == null || packageName.length() == 0) {
612             packageName= IPackageFragment.DEFAULT_PACKAGE_NAME;
613         } else if (typeName.length() > 0 && ScannerHelper.isLowerCase(typeName.charAt(0))) {
614             // see if this is a known package and not a type
615
if (findPackageFragments(packageName + "." + typeName, false) != null) return null; //$NON-NLS-1$
616
}
617
618         // Look for concerned package fragments
619
JavaElementRequestor elementRequestor = new JavaElementRequestor();
620         seekPackageFragments(packageName, false, elementRequestor);
621         IPackageFragment[] packages= elementRequestor.getPackageFragments();
622
623         // Try to find type in package fragments list
624
IType type = null;
625         int length= packages.length;
626         HashSet projects = null;
627         IJavaProject javaProject = null;
628         Answer suggestedAnswer = null;
629         for (int i= 0; i < length; i++) {
630             type = findType(typeName, packages[i], partialMatch, acceptFlags);
631             if (type != null) {
632                 AccessRestriction accessRestriction = null;
633                 if (checkRestrictions) {
634                     accessRestriction = getViolatedRestriction(typeName, packageName, type, accessRestriction);
635                 }
636                 Answer answer = new Answer(type, accessRestriction);
637                 if (!answer.ignoreIfBetter()) {
638                     if (answer.isBetter(suggestedAnswer))
639                         return answer;
640                 } else if (answer.isBetter(suggestedAnswer))
641                     // remember suggestion and keep looking
642
suggestedAnswer = answer;
643             }
644             else if (suggestedAnswer == null && considerSecondaryTypes) {
645                 if (javaProject == null) {
646                     javaProject = packages[i].getJavaProject();
647                 } else if (projects == null) {
648                     if (!javaProject.equals(packages[i].getJavaProject())) {
649                         projects = new HashSet(3);
650                         projects.add(javaProject);
651                         projects.add(packages[i].getJavaProject());
652                     }
653                 } else {
654                     projects.add(packages[i].getJavaProject());
655                 }
656             }
657         }
658         if (suggestedAnswer != null)
659             // no better answer was found
660
return suggestedAnswer;
661
662         // If type was not found, try to find it as secondary in source folders
663
if (considerSecondaryTypes && javaProject != null) {
664             if (projects == null) {
665                 type = findSecondaryType(packageName, typeName, javaProject, waitForIndexes, monitor);
666             } else {
667                 Iterator allProjects = projects.iterator();
668                 while (type == null && allProjects.hasNext()) {
669                     type = findSecondaryType(packageName, typeName, (IJavaProject) allProjects.next(), waitForIndexes, monitor);
670                 }
671             }
672         }
673         return type == null ? null : new Answer(type, null);
674     }
675
676     private AccessRestriction getViolatedRestriction(String JavaDoc typeName, String JavaDoc packageName, IType type, AccessRestriction accessRestriction) {
677         PackageFragmentRoot root = (PackageFragmentRoot) type.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
678         ClasspathEntry entry = (ClasspathEntry) this.rootToResolvedEntries.get(root);
679         if (entry != null) { // reverse map always contains resolved CP entry
680
AccessRuleSet accessRuleSet = entry.getAccessRuleSet();
681             if (accessRuleSet != null) {
682                 // TODO (philippe) improve char[] <-> String conversions to avoid performing them on the fly
683
char[][] packageChars = CharOperation.splitOn('.', packageName.toCharArray());
684                 char[] typeChars = typeName.toCharArray();
685                 accessRestriction = accessRuleSet.getViolatedRestriction(CharOperation.concatWith(packageChars, typeChars, '/'));
686             }
687         }
688         return accessRestriction;
689     }
690
691     /**
692      * Returns the first type in the given package whose name
693      * matches the given (unqualified) name, or <code>null</code> if none
694      * exist. Specifying a <code>null</code> package will result in no matches.
695      * The domain of the search is bounded by the Java project from which
696      * this name lookup was obtained.
697      *
698      * @param name the name of the type to find
699      * @param pkg the package to search
700      * @param partialMatch partial name matches qualify when <code>true</code>,
701      * only exact name matches qualify when <code>false</code>
702      * @param acceptFlags a bit mask describing if classes, interfaces or both classes and interfaces
703      * are desired results. If no flags are specified, all types are returned.
704      * @param considerSecondaryTypes flag to know whether secondary types has to be considered
705      * during the search
706      *
707      * @see #ACCEPT_CLASSES
708      * @see #ACCEPT_INTERFACES
709      * @see #ACCEPT_ENUMS
710      * @see #ACCEPT_ANNOTATIONS
711      */

712     public IType findType(String JavaDoc name, IPackageFragment pkg, boolean partialMatch, int acceptFlags, boolean considerSecondaryTypes) {
713         IType type = findType(name, pkg, partialMatch, acceptFlags);
714         if (type == null && considerSecondaryTypes) {
715             type = findSecondaryType(pkg.getElementName(), name, pkg.getJavaProject(), false, null);
716         }
717         return type;
718     }
719
720     /**
721      * Returns the first type in the given package whose name
722      * matches the given (unqualified) name, or <code>null</code> if none
723      * exist. Specifying a <code>null</code> package will result in no matches.
724      * The domain of the search is bounded by the Java project from which
725      * this name lookup was obtained.
726      * <br>
727      * Note that this method does not find secondary types.
728      * <br>
729      * @param name the name of the type to find
730      * @param pkg the package to search
731      * @param partialMatch partial name matches qualify when <code>true</code>,
732      * only exact name matches qualify when <code>false</code>
733      * @param acceptFlags a bit mask describing if classes, interfaces or both classes and interfaces
734      * are desired results. If no flags are specified, all types are returned.
735      *
736      * @see #ACCEPT_CLASSES
737      * @see #ACCEPT_INTERFACES
738      * @see #ACCEPT_ENUMS
739      * @see #ACCEPT_ANNOTATIONS
740      */

741     public IType findType(String JavaDoc name, IPackageFragment pkg, boolean partialMatch, int acceptFlags) {
742         if (pkg == null) return null;
743
744         // Return first found (ignore duplicates).
745
SingleTypeRequestor typeRequestor = new SingleTypeRequestor();
746         seekTypes(name, pkg, partialMatch, acceptFlags, typeRequestor);
747         return typeRequestor.getType();
748     }
749
750     /**
751      * Returns the type specified by the qualified name, or <code>null</code>
752      * if none exist. The domain of
753      * the search is bounded by the Java project from which this name lookup was obtained.
754      *
755      * @param name the name of the type to find
756      * @param partialMatch partial name matches qualify when <code>true</code>,
757      * only exact name matches qualify when <code>false</code>
758      * @param acceptFlags a bit mask describing if classes, interfaces or both classes and interfaces
759      * are desired results. If no flags are specified, all types are returned.
760      *
761      * @see #ACCEPT_CLASSES
762      * @see #ACCEPT_INTERFACES
763      * @see #ACCEPT_ENUMS
764      * @see #ACCEPT_ANNOTATIONS
765      */

766     public IType findType(String JavaDoc name, boolean partialMatch, int acceptFlags) {
767         NameLookup.Answer answer = findType(name, partialMatch, acceptFlags, false/*don't check restrictions*/);
768         return answer == null ? null : answer.type;
769     }
770         
771     public Answer findType(String JavaDoc name, boolean partialMatch, int acceptFlags, boolean checkRestrictions) {
772         return findType(name, partialMatch, acceptFlags, true/*consider secondary types*/, true/*wait for indexes*/, checkRestrictions, null);
773     }
774     public Answer findType(String JavaDoc name, boolean partialMatch, int acceptFlags, boolean considerSecondaryTypes, boolean waitForIndexes, boolean checkRestrictions, IProgressMonitor monitor) {
775         int index= name.lastIndexOf('.');
776         String JavaDoc className= null, packageName= null;
777         if (index == -1) {
778             packageName= IPackageFragment.DEFAULT_PACKAGE_NAME;
779             className= name;
780         } else {
781             packageName= name.substring(0, index);
782             className= name.substring(index + 1);
783         }
784         return findType(className, packageName, partialMatch, acceptFlags, considerSecondaryTypes, waitForIndexes, checkRestrictions, monitor);
785     }
786
787     private IType getMemberType(IType type, String JavaDoc name, int dot) {
788         while (dot != -1) {
789             int start = dot+1;
790             dot = name.indexOf('.', start);
791             String JavaDoc typeName = name.substring(start, dot == -1 ? name.length() : dot);
792             type = type.getType(typeName);
793         }
794         return type;
795     }
796     
797     public boolean isPackage(String JavaDoc[] pkgName) {
798         return this.packageFragments.get(pkgName) != null;
799     }
800
801     /**
802      * Returns true if the given element's name matches the
803      * specified <code>searchName</code>, otherwise false.
804      *
805      * <p>The <code>partialMatch</code> argument indicates partial matches
806      * should be considered.
807      * NOTE: in partialMatch mode, the case will be ignored, and the searchName must already have
808      * been lowercased.
809      */

810     protected boolean nameMatches(String JavaDoc searchName, IJavaElement element, boolean partialMatch) {
811         if (partialMatch) {
812             // partial matches are used in completion mode, thus case insensitive mode
813
return element.getElementName().toLowerCase().startsWith(searchName);
814         } else {
815             return element.getElementName().equals(searchName);
816         }
817     }
818
819     /**
820      * Returns true if the given cu's name matches the
821      * specified <code>searchName</code>, otherwise false.
822      *
823      * <p>The <code>partialMatch</code> argument indicates partial matches
824      * should be considered.
825      * NOTE: in partialMatch mode, the case will be ignored, and the searchName must already have
826      * been lowercased.
827      */

828     protected boolean nameMatches(String JavaDoc searchName, ICompilationUnit cu, boolean partialMatch) {
829         if (partialMatch) {
830             // partial matches are used in completion mode, thus case insensitive mode
831
return cu.getElementName().toLowerCase().startsWith(searchName);
832         } else {
833             return Util.equalsIgnoreJavaLikeExtension(cu.getElementName(), searchName);
834         }
835     }
836
837     /**
838      * Notifies the given requestor of all package fragments with the
839      * given name. Checks the requestor at regular intervals to see if the
840      * requestor has canceled. The domain of
841      * the search is bounded by the <code>IJavaProject</code>
842      * this <code>NameLookup</code> was obtained from.
843      *
844      * @param partialMatch partial name matches qualify when <code>true</code>;
845      * only exact name matches qualify when <code>false</code>
846      */

847     public void seekPackageFragments(String JavaDoc name, boolean partialMatch, IJavaElementRequestor requestor) {
848 /* if (VERBOSE) {
849             Util.verbose(" SEEKING PACKAGE FRAGMENTS"); //$NON-NLS-1$
850             Util.verbose(" -> name: " + name); //$NON-NLS-1$
851             Util.verbose(" -> partial match:" + partialMatch); //$NON-NLS-1$
852         }
853 */
if (partialMatch) {
854             String JavaDoc[] splittedName = Util.splitOn('.', name, 0, name.length());
855             Object JavaDoc[][] keys = this.packageFragments.keyTable;
856             for (int i = 0, length = keys.length; i < length; i++) {
857                 if (requestor.isCanceled())
858                     return;
859                 String JavaDoc[] pkgName = (String JavaDoc[]) keys[i];
860                 if (pkgName != null && Util.startsWithIgnoreCase(pkgName, splittedName, partialMatch)) {
861                     Object JavaDoc value = this.packageFragments.valueTable[i];
862                     if (value instanceof PackageFragmentRoot) {
863                         PackageFragmentRoot root = (PackageFragmentRoot) value;
864                         requestor.acceptPackageFragment(root.getPackageFragment(pkgName));
865                     } else {
866                         IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) value;
867                         for (int j = 0, length2 = roots.length; j < length2; j++) {
868                             if (requestor.isCanceled())
869                                 return;
870                             PackageFragmentRoot root = (PackageFragmentRoot) roots[j];
871                             requestor.acceptPackageFragment(root.getPackageFragment(pkgName));
872                         }
873                     }
874                 }
875             }
876         } else {
877             String JavaDoc[] splittedName = Util.splitOn('.', name, 0, name.length());
878             Object JavaDoc value = this.packageFragments.get(splittedName);
879             if (value instanceof PackageFragmentRoot) {
880                 requestor.acceptPackageFragment(((PackageFragmentRoot) value).getPackageFragment(splittedName));
881             } else {
882                 IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) value;
883                 if (roots != null) {
884                     for (int i = 0, length = roots.length; i < length; i++) {
885                         if (requestor.isCanceled())
886                             return;
887                         PackageFragmentRoot root = (PackageFragmentRoot) roots[i];
888                         requestor.acceptPackageFragment(root.getPackageFragment(splittedName));
889                     }
890                 }
891             }
892         }
893     }
894
895     /**
896      * Notifies the given requestor of all types (classes and interfaces) in the
897      * given package fragment with the given (unqualified) name.
898      * Checks the requestor at regular intervals to see if the requestor
899      * has canceled. If the given package fragment is <code>null</code>, all types in the
900      * project whose simple name matches the given name are found.
901      *
902      * @param name The name to search
903      * @param pkg The corresponding package fragment
904      * @param partialMatch partial name matches qualify when <code>true</code>;
905      * only exact name matches qualify when <code>false</code>
906      * @param acceptFlags a bit mask describing if classes, interfaces or both classes and interfaces
907      * are desired results. If no flags are specified, all types are returned.
908      * @param requestor The requestor that collects the result
909      *
910      * @see #ACCEPT_CLASSES
911      * @see #ACCEPT_INTERFACES
912      * @see #ACCEPT_ENUMS
913      * @see #ACCEPT_ANNOTATIONS
914      */

915     public void seekTypes(String JavaDoc name, IPackageFragment pkg, boolean partialMatch, int acceptFlags, IJavaElementRequestor requestor) {
916 /* if (VERBOSE) {
917             Util.verbose(" SEEKING TYPES"); //$NON-NLS-1$
918             Util.verbose(" -> name: " + name); //$NON-NLS-1$
919             Util.verbose(" -> pkg: " + ((JavaElement) pkg).toStringWithAncestors()); //$NON-NLS-1$
920             Util.verbose(" -> partial match:" + partialMatch); //$NON-NLS-1$
921         }
922 */

923         String JavaDoc matchName= partialMatch ? name.toLowerCase() : name;
924         if (pkg == null) {
925             findAllTypes(matchName, partialMatch, acceptFlags, requestor);
926             return;
927         }
928         IPackageFragmentRoot root= (IPackageFragmentRoot) pkg.getParent();
929         try {
930
931             // look in working copies first
932
int firstDot = -1;
933             String JavaDoc topLevelTypeName = null;
934             int packageFlavor= root.getKind();
935             if (this.typesInWorkingCopies != null || packageFlavor == IPackageFragmentRoot.K_SOURCE) {
936                 firstDot = matchName.indexOf('.');
937                 if (!partialMatch)
938                     topLevelTypeName = firstDot == -1 ? matchName : matchName.substring(0, firstDot);
939             }
940             if (this.typesInWorkingCopies != null) {
941                 if (seekTypesInWorkingCopies(matchName, pkg, firstDot, partialMatch, topLevelTypeName, acceptFlags, requestor))
942                     return;
943             }
944             
945             // look in model
946
switch (packageFlavor) {
947                 case IPackageFragmentRoot.K_BINARY :
948                     matchName= matchName.replace('.', '$');
949                     seekTypesInBinaryPackage(matchName, pkg, partialMatch, acceptFlags, requestor);
950                     break;
951                 case IPackageFragmentRoot.K_SOURCE :
952                     seekTypesInSourcePackage(matchName, pkg, firstDot, partialMatch, topLevelTypeName, acceptFlags, requestor);
953                     break;
954                 default :
955                     return;
956             }
957         } catch (JavaModelException e) {
958             return;
959         }
960     }
961
962     /**
963      * Performs type search in a binary package.
964      */

965     protected void seekTypesInBinaryPackage(String JavaDoc name, IPackageFragment pkg, boolean partialMatch, int acceptFlags, IJavaElementRequestor requestor) {
966         long start = -1;
967         if (VERBOSE)
968             start = System.currentTimeMillis();
969         try {
970             if (!partialMatch) {
971                 // exact match
972
if (requestor.isCanceled()) return;
973                 ClassFile classFile = new ClassFile((PackageFragment) pkg, name);
974                 if (classFile.existsUsingJarTypeCache()) {
975                     IType type = classFile.getType();
976                     if (acceptType(type, acceptFlags, false/*not a source type*/)) {
977                         requestor.acceptType(type);
978                     }
979                 }
980             } else {
981                 IJavaElement[] classFiles= null;
982                 try {
983                     classFiles= pkg.getChildren();
984                 } catch (JavaModelException npe) {
985                     return; // the package is not present
986
}
987                 int length= classFiles.length;
988                 String JavaDoc unqualifiedName = name;
989                 int index = name.lastIndexOf('$');
990                 if (index != -1) {
991                     //the type name of the inner type
992
unqualifiedName = Util.localTypeName(name, index, name.length());
993                     // unqualifiedName is empty if the name ends with a '$' sign.
994
// See http://dev.eclipse.org/bugs/show_bug.cgi?id=14642
995
}
996                 int matchLength = name.length();
997                 for (int i = 0; i < length; i++) {
998                     if (requestor.isCanceled())
999                         return;
1000                    IJavaElement classFile= classFiles[i];
1001                    // MatchName will never have the extension ".class" and the elementName always will.
1002
String JavaDoc elementName = classFile.getElementName();
1003                    if (elementName.regionMatches(true /*ignore case*/, 0, name, 0, matchLength)) {
1004                        IType type = ((ClassFile) classFile).getType();
1005                        String JavaDoc typeName = type.getElementName();
1006                        if (typeName.length() > 0 && !Character.isDigit(typeName.charAt(0))) { //not an anonymous type
1007
if (nameMatches(unqualifiedName, type, true/*partial match*/) && acceptType(type, acceptFlags, false/*not a source type*/))
1008                                requestor.acceptType(type);
1009                        }
1010                    }
1011                }
1012            }
1013        } finally {
1014            if (VERBOSE)
1015                this.timeSpentInSeekTypesInBinaryPackage += System.currentTimeMillis()-start;
1016        }
1017    }
1018
1019    /**
1020     * Performs type search in a source package.
1021     */

1022    protected void seekTypesInSourcePackage(
1023            String JavaDoc name,
1024            IPackageFragment pkg,
1025            int firstDot,
1026            boolean partialMatch,
1027            String JavaDoc topLevelTypeName,
1028            int acceptFlags,
1029            IJavaElementRequestor requestor) {
1030        
1031        long start = -1;
1032        if (VERBOSE)
1033            start = System.currentTimeMillis();
1034        try {
1035            if (!partialMatch) {
1036                try {
1037                    IJavaElement[] compilationUnits = pkg.getChildren();
1038                    for (int i = 0, length = compilationUnits.length; i < length; i++) {
1039                        if (requestor.isCanceled())
1040                            return;
1041                        IJavaElement cu = compilationUnits[i];
1042                        String JavaDoc cuName = cu.getElementName();
1043                        int lastDot = cuName.lastIndexOf('.');
1044                        if (lastDot != topLevelTypeName.length() || !topLevelTypeName.regionMatches(0, cuName, 0, lastDot))
1045                            continue;
1046                        IType type = ((ICompilationUnit) cu).getType(topLevelTypeName);
1047                        type = getMemberType(type, name, firstDot);
1048                        if (acceptType(type, acceptFlags, true/*a source type*/)) { // accept type checks for existence
1049
requestor.acceptType(type);
1050                            break; // since an exact match was requested, no other matching type can exist
1051
}
1052                    }
1053                } catch (JavaModelException e) {
1054                    // package doesn't exist -> ignore
1055
}
1056            } else {
1057                try {
1058                    String JavaDoc cuPrefix = firstDot == -1 ? name : name.substring(0, firstDot);
1059                    IJavaElement[] compilationUnits = pkg.getChildren();
1060                    for (int i = 0, length = compilationUnits.length; i < length; i++) {
1061                        if (requestor.isCanceled())
1062                            return;
1063                        IJavaElement cu = compilationUnits[i];
1064                        if (!cu.getElementName().toLowerCase().startsWith(cuPrefix))
1065                            continue;
1066                        try {
1067                            IType[] types = ((ICompilationUnit) cu).getTypes();
1068                            for (int j = 0, typeLength = types.length; j < typeLength; j++)
1069                                seekTypesInTopLevelType(name, firstDot, types[j], requestor, acceptFlags);
1070                        } catch (JavaModelException e) {
1071                            // cu doesn't exist -> ignore
1072
}
1073                    }
1074                } catch (JavaModelException e) {
1075                    // package doesn't exist -> ignore
1076
}
1077            }
1078        } finally {
1079            if (VERBOSE)
1080                this.timeSpentInSeekTypesInSourcePackage += System.currentTimeMillis()-start;
1081        }
1082    }
1083    
1084    /**
1085     * Notifies the given requestor of all types (classes and interfaces) in the
1086     * given type with the given (possibly qualified) name. Checks
1087     * the requestor at regular intervals to see if the requestor
1088     * has canceled.
1089     */

1090    protected boolean seekTypesInType(String JavaDoc prefix, int firstDot, IType type, IJavaElementRequestor requestor, int acceptFlags) {
1091        IType[] types= null;
1092        try {
1093            types= type.getTypes();
1094        } catch (JavaModelException npe) {
1095            return false; // the enclosing type is not present
1096
}
1097        int length= types.length;
1098        if (length == 0) return false;
1099        
1100        String JavaDoc memberPrefix = prefix;
1101        boolean isMemberTypePrefix = false;
1102        if (firstDot != -1) {
1103            memberPrefix= prefix.substring(0, firstDot);
1104            isMemberTypePrefix = true;
1105        }
1106        for (int i= 0; i < length; i++) {
1107            if (requestor.isCanceled())
1108                return false;
1109            IType memberType= types[i];
1110            if (memberType.getElementName().toLowerCase().startsWith(memberPrefix))
1111                if (isMemberTypePrefix) {
1112                    String JavaDoc subPrefix = prefix.substring(firstDot + 1, prefix.length());
1113                    return seekTypesInType(subPrefix, subPrefix.indexOf('.'), memberType, requestor, acceptFlags);
1114                } else {
1115                    if (acceptType(memberType, acceptFlags, true/*a source type*/)) {
1116                        requestor.acceptMemberType(memberType);
1117                        return true;
1118                    }
1119                }
1120        }
1121        return false;
1122    }
1123    
1124    protected boolean seekTypesInTopLevelType(String JavaDoc prefix, int firstDot, IType topLevelType, IJavaElementRequestor requestor, int acceptFlags) {
1125        if (!topLevelType.getElementName().toLowerCase().startsWith(prefix))
1126            return false;
1127        if (firstDot == -1) {
1128            if (acceptType(topLevelType, acceptFlags, true/*a source type*/)) {
1129                requestor.acceptType(topLevelType);
1130                return true;
1131            }
1132        } else {
1133            return seekTypesInType(prefix, firstDot, topLevelType, requestor, acceptFlags);
1134        }
1135        return false;
1136    }
1137    
1138    /*
1139     * Seeks the type with the given name in the map of types with precedence (coming from working copies)
1140     * Return whether a type has been found.
1141     */

1142    protected boolean seekTypesInWorkingCopies(
1143            String JavaDoc name,
1144            IPackageFragment pkg,
1145            int firstDot,
1146            boolean partialMatch,
1147            String JavaDoc topLevelTypeName,
1148            int acceptFlags,
1149            IJavaElementRequestor requestor) {
1150
1151        if (!partialMatch) {
1152            HashMap typeMap = (HashMap) (this.typesInWorkingCopies == null ? null : this.typesInWorkingCopies.get(pkg));
1153            if (typeMap != null) {
1154                Object JavaDoc object = typeMap.get(topLevelTypeName);
1155                if (object instanceof IType) {
1156                    IType type = getMemberType((IType) object, name, firstDot);
1157                    if (acceptType(type, acceptFlags, true/*a source type*/)) {
1158                        requestor.acceptType(type);
1159                        return true; // don't continue with compilation unit
1160
}
1161                } else if (object instanceof IType[]) {
1162                    if (object == NO_TYPES) return true; // all types where deleted -> type is hidden
1163
IType[] topLevelTypes = (IType[]) object;
1164                    for (int i = 0, length = topLevelTypes.length; i < length; i++) {
1165                        if (requestor.isCanceled())
1166                            return false;
1167                        IType type = getMemberType(topLevelTypes[i], name, firstDot);
1168                        if (acceptType(type, acceptFlags, true/*a source type*/)) {
1169                            requestor.acceptType(type);
1170                            return true; // return the first one
1171
}
1172                    }
1173                }
1174            }
1175        } else {
1176            HashMap typeMap = (HashMap) (this.typesInWorkingCopies == null ? null : this.typesInWorkingCopies.get(pkg));
1177            if (typeMap != null) {
1178                Iterator iterator = typeMap.values().iterator();
1179                while (iterator.hasNext()) {
1180                    if (requestor.isCanceled())
1181                        return false;
1182                    Object JavaDoc object = iterator.next();
1183                    if (object instanceof IType) {
1184                        seekTypesInTopLevelType(name, firstDot, (IType) object, requestor, acceptFlags);
1185                    } else if (object instanceof IType[]) {
1186                        IType[] topLevelTypes = (IType[]) object;
1187                        for (int i = 0, length = topLevelTypes.length; i < length; i++)
1188                            seekTypesInTopLevelType(name, firstDot, topLevelTypes[i], requestor, acceptFlags);
1189                    }
1190                }
1191            }
1192        }
1193        return false;
1194    }
1195    
1196}
1197
Popular Tags