1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core;
14 import java.util.ArrayList;
15 import java.util.HashMap;
18 import net.sourceforge.phpdt.core.IClasspathEntry;
19 import net.sourceforge.phpdt.core.IJavaElement;
20 import net.sourceforge.phpdt.core.IJavaProject;
21 import net.sourceforge.phpdt.core.IPackageFragment;
22 import net.sourceforge.phpdt.core.IPackageFragmentRoot;
23 import net.sourceforge.phpdt.core.IType;
24 import net.sourceforge.phpdt.core.IWorkingCopy;
25 import net.sourceforge.phpdt.core.JavaModelException;
26 import net.sourceforge.phpdt.core.ICompilationUnit;
27 import net.sourceforge.phpdt.internal.core.util.PerThreadObject;
28 import net.sourceforge.phpeclipse.PHPCore;
30 import org.eclipse.core.resources.IResource;
31 import org.eclipse.core.resources.IWorkspace;
32 import org.eclipse.core.resources.ResourcesPlugin;
33 import org.eclipse.core.runtime.IPath;
35 * A <code>NameLookup</code> provides name resolution within a Java project.
36 * The name lookup facility uses the project's classpath to prioritize the
37 * order in which package fragments are searched when resolving a name.
39 * <p>Name lookup only returns a handle when the named element actually
40 * exists in the model; otherwise <code>null</code> is returned.
42 * <p>There are two logical sets of methods within this interface. Methods
43 * which start with <code>find*</code> are intended to be convenience methods for quickly
44 * finding an element within another element; for instance, for finding a class within a
45 * package. The other set of methods all begin with <code>seek*</code>. These methods
46 * do comprehensive searches of the <code>IJavaProject</code> returning hits
47 * in real time through an <code>IJavaElementRequestor</code>.
50 public class NameLookup {
52 * Accept flag for specifying classes.
54 public static final int ACCEPT_CLASSES = 0x00000002;
57 * Accept flag for specifying interfaces.
59 public static final int ACCEPT_INTERFACES = 0x00000004;
62 * The <code>IPackageFragmentRoot</code>'s associated
63 * with the classpath of this NameLookup facility's
66 protected IPackageFragmentRoot[] fPackageFragmentRoots= null;
69 * Table that maps package names to lists of package fragments for
70 * all package fragments in the package fragment roots known
71 * by this name lookup facility. To allow > 1 package fragment
72 * with the same name, values are arrays of package fragments
73 * ordered as they appear on the classpath.
75 protected Map fPackageFragments;
78 * The <code>IWorkspace</code> that this NameLookup
79 * is configure within.
81 protected IWorkspace workspace;
84 * A map from compilation unit handles to units to look inside (compilation
85 * units or working copies).
86 * Allows working copies to take precedence over compilation units.
87 * The cache is a 2-level cache, first keyed by thread.
89 protected PerThreadObject unitsToLookInside = new PerThreadObject();
91 public NameLookup(IJavaProject project) throws JavaModelException {
92 configureFromProject(project);
96 * Returns true if:<ul>
97 * <li>the given type is an existing class and the flag's <code>ACCEPT_CLASSES</code>
99 * <li>the given type is an existing interface and the <code>ACCEPT_INTERFACES</code>
101 * <li>neither the <code>ACCEPT_CLASSES</code> or <code>ACCEPT_INTERFACES</code>
104 * Otherwise, false is returned.
106 protected boolean acceptType(IType type, int acceptFlags) {
107 if (acceptFlags == 0)
108 return true; // no flags, always accepted
110 if (type.isClass()) {
111 return (acceptFlags & ACCEPT_CLASSES) != 0;
113 return (acceptFlags & ACCEPT_INTERFACES) != 0;
115 } catch (JavaModelException npe) {
116 return false; // the class is not present, do not accept.
121 * Configures this <code>NameLookup</code> based on the
122 * info of the given <code>IJavaProject</code>.
124 * @throws JavaModelException if the <code>IJavaProject</code> has no classpath.
126 private void configureFromProject(IJavaProject project) throws JavaModelException {
127 workspace= ResourcesPlugin.getWorkspace();
128 fPackageFragmentRoots= ((JavaProject) project).getAllPackageFragmentRoots();
129 fPackageFragments= new HashMap();
130 IPackageFragment[] frags = this.getPackageFragmentsInRoots(fPackageFragmentRoots, project);
131 for (int i= 0; i < frags.length; i++) {
132 IPackageFragment fragment= frags[i];
133 IPackageFragment[] entry= (IPackageFragment[]) fPackageFragments.get(fragment.getElementName());
135 entry= new IPackageFragment[1];
137 fPackageFragments.put(fragment.getElementName(), entry);
139 IPackageFragment[] copy= new IPackageFragment[entry.length + 1];
140 System.arraycopy(entry, 0, copy, 0, entry.length);
141 copy[entry.length]= fragment;
142 fPackageFragments.put(fragment.getElementName(), copy);
148 * Finds every type in the project whose simple name matches
149 * the prefix, informing the requestor of each hit. The requestor
150 * is polled for cancellation at regular intervals.
152 * <p>The <code>partialMatch</code> argument indicates partial matches
153 * should be considered.
155 private void findAllTypes(String prefix, boolean partialMatch, int acceptFlags, IJavaElementRequestor requestor) {
156 int count= fPackageFragmentRoots.length;
157 for (int i= 0; i < count; i++) {
158 if (requestor.isCanceled())
160 IPackageFragmentRoot root= fPackageFragmentRoots[i];
161 IJavaElement[] packages= null;
163 packages= root.getChildren();
164 } catch (JavaModelException npe) {
165 continue; // the root is not present, continue;
167 if (packages != null) {
168 for (int j= 0, packageCount= packages.length; j < packageCount; j++) {
169 if (requestor.isCanceled())
171 seekTypes(prefix, (IPackageFragment) packages[j], partialMatch, acceptFlags, requestor);
178 * Returns the <code>ICompilationUnit</code> which defines the type
179 * named <code>qualifiedTypeName</code>, or <code>null</code> if
180 * none exists. The domain of the search is bounded by the classpath
181 * of the <code>IJavaProject</code> this <code>NameLookup</code> was
184 * The name must be fully qualified (eg "java.lang.Object", "java.util.Hashtable$Entry")
186 public ICompilationUnit findCompilationUnit(String qualifiedTypeName) {
187 String pkgName= IPackageFragment.DEFAULT_PACKAGE_NAME;
188 String cuName= qualifiedTypeName;
190 int index= qualifiedTypeName.lastIndexOf('.');
192 pkgName= qualifiedTypeName.substring(0, index);
193 cuName= qualifiedTypeName.substring(index + 1);
195 index= cuName.indexOf('$');
197 cuName= cuName.substring(0, index);
199 cuName += ".java"; //$NON-NLS-1$
200 IPackageFragment[] frags= (IPackageFragment[]) fPackageFragments.get(pkgName);
202 for (int i= 0; i < frags.length; i++) {
203 IPackageFragment frag= frags[i];
204 // if (!(frag instanceof JarPackageFragment)) {
205 // ICompilationUnit cu= frag.getCompilationUnit(cuName);
206 // if (cu != null && cu.exists()) {
216 * Returns the package fragment whose path matches the given
217 * (absolute) path, or <code>null</code> if none exist. The domain of
218 * the search is bounded by the classpath of the <code>IJavaProject</code>
219 * this <code>NameLookup</code> was obtained from.
221 * - internal to the workbench: "/Project/src"
222 * - external to the workbench: "c:/jdk/classes.zip/java/lang"
224 public IPackageFragment findPackageFragment(IPath path) {
225 if (!path.isAbsolute()) {
226 throw new IllegalArgumentException(Util.bind("path.mustBeAbsolute")); //$NON-NLS-1$
229 * this code should rather use the package fragment map to find the candidate package, then
230 * check if the respective enclosing root maps to the one on this given IPath.
232 IResource possibleFragment = workspace.getRoot().findMember(path);
233 if (possibleFragment == null) {
235 for (int i = 0; i < fPackageFragmentRoots.length; i++) {
236 IPackageFragmentRoot root = fPackageFragmentRoots[i];
237 if (!root.isExternal()) {
240 IPath rootPath = root.getPath();
241 int matchingCount = rootPath.matchingFirstSegments(path);
242 if (matchingCount != 0) {
243 String name = path.toOSString();
244 // + 1 is for the File.separatorChar
245 name = name.substring(rootPath.toOSString().length() + 1, name.length());
246 name = name.replace(File.separatorChar, '.');
247 IJavaElement[] list = null;
249 list = root.getChildren();
250 } catch (JavaModelException npe) {
251 continue; // the package fragment root is not present;
253 int elementCount = list.length;
254 for (int j = 0; j < elementCount; j++) {
255 IPackageFragment packageFragment = (IPackageFragment) list[j];
256 if (nameMatches(name, packageFragment, false)) {
257 return packageFragment;
263 IJavaElement fromFactory = PHPCore.create(possibleFragment);
264 if (fromFactory == null) {
267 if (fromFactory instanceof IPackageFragment) {
268 return (IPackageFragment) fromFactory;
270 if (fromFactory instanceof IJavaProject) {
271 // default package in a default root
272 JavaProject project = (JavaProject) fromFactory;
274 IClasspathEntry entry = project.getClasspathEntryFor(path);
276 IPackageFragmentRoot root =
277 project.getPackageFragmentRoot(project.getResource());
278 IPackageFragment[] pkgs = (IPackageFragment[]) fPackageFragments.get(IPackageFragment.DEFAULT_PACKAGE_NAME);
282 for (int i = 0; i < pkgs.length; i++) {
283 if (pkgs[i].getParent().equals(root)) {
288 } catch (JavaModelException e) {
297 * Returns the package fragments whose name matches the given
298 * (qualified) name, or <code>null</code> if none exist.
302 * - qualified: "pack.pack1.pack2"
303 * @param partialMatch partial name matches qualify when <code>true</code>,
304 * only exact name matches qualify when <code>false</code>
306 public IPackageFragment[] findPackageFragments(String name, boolean partialMatch) {
307 int count= fPackageFragmentRoots.length;
309 name= name.toLowerCase();
310 for (int i= 0; i < count; i++) {
311 IPackageFragmentRoot root= fPackageFragmentRoots[i];
312 IJavaElement[] list= null;
314 list= root.getChildren();
315 } catch (JavaModelException npe) {
316 continue; // the package fragment root is not present;
318 int elementCount= list.length;
319 IPackageFragment[] result = new IPackageFragment[elementCount];
320 int resultLength = 0;
321 for (int j= 0; j < elementCount; j++) {
322 IPackageFragment packageFragment= (IPackageFragment) list[j];
323 if (nameMatches(name, packageFragment, true)) {
324 result[resultLength++] = packageFragment;
327 if (resultLength > 0) {
328 System.arraycopy(result, 0, result = new IPackageFragment[resultLength], 0, resultLength);
335 IPackageFragment[] fragments= (IPackageFragment[]) fPackageFragments.get(name);
336 if (fragments != null) {
337 IPackageFragment[] result = new IPackageFragment[fragments.length];
338 int resultLength = 0;
339 for (int i= 0; i < fragments.length; i++) {
340 IPackageFragment packageFragment= fragments[i];
341 result[resultLength++] = packageFragment;
343 if (resultLength > 0) {
344 System.arraycopy(result, 0, result = new IPackageFragment[resultLength], 0, resultLength);
357 public IType findType(String typeName, String packageName, boolean partialMatch, int acceptFlags) {
358 if (packageName == null) {
359 packageName= IPackageFragment.DEFAULT_PACKAGE_NAME;
361 JavaElementRequestor elementRequestor = new JavaElementRequestor();
362 seekPackageFragments(packageName, false, elementRequestor);
363 IPackageFragment[] packages= elementRequestor.getPackageFragments();
365 for (int i= 0, length= packages.length; i < length; i++) {
366 IType type= findType(typeName, packages[i], partialMatch, acceptFlags);
373 * Returns all the package fragments found in the specified
374 * package fragment roots. Make sure the returned fragments have the given
375 * project as great parent. This ensures the name lookup will not refer to another
376 * project (through jar package fragment roots)
378 private IPackageFragment[] getPackageFragmentsInRoots(IPackageFragmentRoot[] roots, IJavaProject project) {
380 // The following code assumes that all the roots have the given project as their parent
381 ArrayList frags = new ArrayList();
382 for (int i = 0; i < roots.length; i++) {
383 IPackageFragmentRoot root = roots[i];
385 IJavaElement[] children = root.getChildren();
387 /* 2 jar package fragment roots can be equals but not belonging
388 to the same project. As a result, they share the same element info.
389 So this jar package fragment root could get the children of
390 another jar package fragment root.
391 The following code ensures that the children of this jar package
392 fragment root have the given project as a great parent.
394 int length = children.length;
395 if (length == 0) continue;
396 if (children[0].getParent().getParent().equals(project)) {
397 // the children have the right parent, simply add them to the list
398 for (int j = 0; j < length; j++) {
399 frags.add(children[j]);
402 // create a new handle with the root as the parent
403 for (int j = 0; j < length; j++) {
404 frags.add(root.getPackageFragment(children[j].getElementName()));
407 } catch (JavaModelException e) {
411 IPackageFragment[] fragments = new IPackageFragment[frags.size()];
412 frags.toArray(fragments);
417 * Returns the first type in the given package whose name
418 * matches the given (unqualified) name, or <code>null</code> if none
419 * exist. Specifying a <code>null</code> package will result in no matches.
420 * The domain of the search is bounded by the Java project from which
421 * this name lookup was obtained.
423 * @param name the name of the type to find
424 * @param pkg the package to search
425 * @param partialMatch partial name matches qualify when <code>true</code>,
426 * only exact name matches qualify when <code>false</code>
427 * @param acceptFlags a bit mask describing if classes, interfaces or both classes and interfaces
428 * are desired results. If no flags are specified, all types are returned.
430 * @see #ACCEPT_CLASSES
431 * @see #ACCEPT_INTERFACES
433 public IType findType(String name, IPackageFragment pkg, boolean partialMatch, int acceptFlags) {
437 // Return first found (ignore duplicates).
438 //synchronized(JavaModelManager.getJavaModelManager()){
439 // SingleTypeRequestor typeRequestor = new SingleTypeRequestor();
440 // seekTypes(name, pkg, partialMatch, acceptFlags, typeRequestor);
441 // IType type= typeRequestor.getType();
448 * Returns the type specified by the qualified name, or <code>null</code>
449 * if none exist. The domain of
450 * the search is bounded by the Java project from which this name lookup was obtained.
452 * @param name the name of the type to find
453 * @param partialMatch partial name matches qualify when <code>true</code>,
454 * only exact name matches qualify when <code>false</code>
455 * @param acceptFlags a bit mask describing if classes, interfaces or both classes and interfaces
456 * are desired results. If no flags are specified, all types are returned.
458 * @see #ACCEPT_CLASSES
459 * @see #ACCEPT_INTERFACES
461 public IType findType(String name, boolean partialMatch, int acceptFlags) {
462 int index= name.lastIndexOf('.');
463 String className= null, packageName= null;
465 packageName= IPackageFragment.DEFAULT_PACKAGE_NAME;
468 packageName= name.substring(0, index);
469 className= name.substring(index + 1);
471 return findType(className, packageName, partialMatch, acceptFlags);
475 * Returns true if the given element's name matches the
476 * specified <code>searchName</code>, otherwise false.
478 * <p>The <code>partialMatch</code> argument indicates partial matches
479 * should be considered.
480 * NOTE: in partialMatch mode, the case will be ignored, and the searchName must already have
483 protected boolean nameMatches(String searchName, IJavaElement element, boolean partialMatch) {
485 // partial matches are used in completion mode, thus case insensitive mode
486 return element.getElementName().toLowerCase().startsWith(searchName);
488 return element.getElementName().equals(searchName);
493 * Notifies the given requestor of all package fragments with the
494 * given name. Checks the requestor at regular intervals to see if the
495 * requestor has canceled. The domain of
496 * the search is bounded by the <code>IJavaProject</code>
497 * this <code>NameLookup</code> was obtained from.
499 * @param partialMatch partial name matches qualify when <code>true</code>;
500 * only exact name matches qualify when <code>false</code>
502 public void seekPackageFragments(String name, boolean partialMatch, IJavaElementRequestor requestor) {
503 int count= fPackageFragmentRoots.length;
504 String matchName= partialMatch ? name.toLowerCase() : name;
505 for (int i= 0; i < count; i++) {
506 if (requestor.isCanceled())
508 IPackageFragmentRoot root= fPackageFragmentRoots[i];
509 IJavaElement[] list= null;
511 list= root.getChildren();
512 } catch (JavaModelException npe) {
513 continue; // this root package fragment is not present
515 int elementCount= list.length;
516 for (int j= 0; j < elementCount; j++) {
517 if (requestor.isCanceled())
519 IPackageFragment packageFragment= (IPackageFragment) list[j];
520 if (nameMatches(matchName, packageFragment, partialMatch))
521 requestor.acceptPackageFragment(packageFragment);
527 * Notifies the given requestor of all types (classes and interfaces) in the
528 * given package fragment with the given (unqualified) name.
529 * Checks the requestor at regular intervals to see if the requestor
530 * has canceled. If the given package fragment is <code>null</code>, all types in the
531 * project whose simple name matches the given name are found.
533 * @param name The name to search
534 * @param pkg The corresponding package fragment
535 * @param partialMatch partial name matches qualify when <code>true</code>;
536 * only exact name matches qualify when <code>false</code>
537 * @param acceptFlags a bit mask describing if classes, interfaces or both classes and interfaces
538 * are desired results. If no flags are specified, all types are returned.
539 * @param requestor The requestor that collects the result
541 * @see #ACCEPT_CLASSES
542 * @see #ACCEPT_INTERFACES
544 public void seekTypes(String name, IPackageFragment pkg, boolean partialMatch, int acceptFlags, IJavaElementRequestor requestor) {
546 String matchName= partialMatch ? name.toLowerCase() : name;
547 if (matchName.indexOf('.') >= 0) { //looks for member type A.B
548 matchName= matchName.replace('.', '$');
551 findAllTypes(matchName, partialMatch, acceptFlags, requestor);
554 IPackageFragmentRoot root= (IPackageFragmentRoot) pkg.getParent();
556 int packageFlavor= root.getKind();
557 switch (packageFlavor) {
558 // case IPackageFragmentRoot.K_BINARY :
559 // seekTypesInBinaryPackage(matchName, pkg, partialMatch, acceptFlags, requestor);
561 case IPackageFragmentRoot.K_SOURCE :
562 seekTypesInSourcePackage(matchName, pkg, partialMatch, acceptFlags, requestor);
567 } catch (JavaModelException e) {
573 * Performs type search in a binary package.
575 // protected void seekTypesInBinaryPackage(String name, IPackageFragment pkg, boolean partialMatch, int acceptFlags, IJavaElementRequestor requestor) {
576 // IClassFile[] classFiles= null;
578 // classFiles= pkg.getClassFiles();
579 // } catch (JavaModelException npe) {
580 // return; // the package is not present
582 // int length= classFiles.length;
584 // String unqualifiedName= name;
585 // int index= name.lastIndexOf('$');
586 // if (index != -1) {
587 // //the type name of the inner type
588 // unqualifiedName= name.substring(index + 1, name.length());
589 // // unqualifiedName is empty if the name ends with a '$' sign.
590 // // See http://dev.eclipse.org/bugs/show_bug.cgi?id=14642
591 // if ((unqualifiedName.length() > 0 && Character.isDigit(unqualifiedName.charAt(0))) || unqualifiedName.length() == 0){
592 // unqualifiedName = name;
595 // String matchName= partialMatch ? name.toLowerCase() : name;
596 // for (int i= 0; i < length; i++) {
597 // if (requestor.isCanceled())
599 // IClassFile classFile= classFiles[i];
600 // String elementName = classFile.getElementName();
601 // if (partialMatch) elementName = elementName.toLowerCase();
604 // * Must use startWith because matchName will never have the
605 // * extension ".class" and the elementName always will.
607 // if (elementName.startsWith(matchName)) {
610 // type= classFile.getType();
611 // } catch (JavaModelException npe) {
612 // continue; // the classFile is not present
614 // if (!partialMatch || (type.getElementName().length() > 0 && !Character.isDigit(type.getElementName().charAt(0)))) { //not an anonymous type
615 // if (nameMatches(unqualifiedName, type, partialMatch) && acceptType(type, acceptFlags))
616 // requestor.acceptType(type);
623 * Performs type search in a source package.
625 protected void seekTypesInSourcePackage(String name, IPackageFragment pkg, boolean partialMatch, int acceptFlags, IJavaElementRequestor requestor) {
626 ICompilationUnit[] compilationUnits = null;
628 compilationUnits = pkg.getCompilationUnits();
629 } catch (JavaModelException npe) {
630 return; // the package is not present
632 int length= compilationUnits.length;
633 String matchName = name;
634 int index= name.indexOf('$');
635 boolean potentialMemberType = false;
636 String potentialMatchName = null;
638 //the compilation unit name of the inner type
639 potentialMatchName = name.substring(0, index);
640 potentialMemberType = true;
644 * In the following, matchName will never have the extension ".java" and
645 * the compilationUnits always will. So add it if we're looking for
648 String unitName = partialMatch ? matchName.toLowerCase() : matchName + ".java"; //$NON-NLS-1$
649 String potentialUnitName = null;
650 if (potentialMemberType) {
651 potentialUnitName = partialMatch ? potentialMatchName.toLowerCase() : potentialMatchName + ".java"; //$NON-NLS-1$
654 for (int i= 0; i < length; i++) {
655 if (requestor.isCanceled())
657 ICompilationUnit compilationUnit= compilationUnits[i];
659 // unit to look inside
660 ICompilationUnit unitToLookInside = null;
661 Map workingCopies = (Map) this.unitsToLookInside.getCurrent();
662 if (workingCopies != null
663 && (unitToLookInside = (ICompilationUnit)workingCopies.get(compilationUnit)) != null){
664 compilationUnit = unitToLookInside;
666 if ((unitToLookInside != null && !potentialMemberType) || nameMatches(unitName, compilationUnit, partialMatch)) {
669 types= compilationUnit.getTypes();
670 } catch (JavaModelException npe) {
671 continue; // the compilation unit is not present
673 int typeLength= types.length;
674 for (int j= 0; j < typeLength; j++) {
675 if (requestor.isCanceled())
677 IType type= types[j];
678 if (nameMatches(matchName, type, partialMatch)) {
679 if (acceptType(type, acceptFlags)) requestor.acceptType(type);
682 } else if (potentialMemberType && nameMatches(potentialUnitName, compilationUnit, partialMatch)) {
685 types= compilationUnit.getTypes();
686 } catch (JavaModelException npe) {
687 continue; // the compilation unit is not present
689 int typeLength= types.length;
690 for (int j= 0; j < typeLength; j++) {
691 if (requestor.isCanceled())
693 IType type= types[j];
694 if (nameMatches(potentialMatchName, type, partialMatch)) {
695 seekQualifiedMemberTypes(name.substring(index + 1, name.length()), type, partialMatch, requestor, acceptFlags);
703 * Remembers a set of compilation units that will be looked inside
704 * when looking up a type. If they are working copies, they take
705 * precedence of their compilation units.
706 * <code>null</code> means that no special compilation units should be used.
708 public void setUnitsToLookInside(IWorkingCopy[] unitsToLookInside) {
710 if (unitsToLookInside == null) {
711 this.unitsToLookInside.setCurrent(null);
713 HashMap workingCopies = new HashMap();
714 this.unitsToLookInside.setCurrent(workingCopies);
715 for (int i = 0, length = unitsToLookInside.length; i < length; i++) {
716 IWorkingCopy unitToLookInside = unitsToLookInside[i];
717 ICompilationUnit original = (ICompilationUnit)unitToLookInside.getOriginalElement();
718 if (original != null) {
719 workingCopies.put(original, unitToLookInside);
721 workingCopies.put(unitToLookInside, unitToLookInside);
728 * Notifies the given requestor of all types (classes and interfaces) in the
729 * given type with the given (possibly qualified) name. Checks
730 * the requestor at regular intervals to see if the requestor
733 * @param partialMatch partial name matches qualify when <code>true</code>,
734 * only exact name matches qualify when <code>false</code>
736 protected void seekQualifiedMemberTypes(String qualifiedName, IType type, boolean partialMatch, IJavaElementRequestor requestor, int acceptFlags) {
741 types= type.getTypes();
742 } catch (JavaModelException npe) {
743 return; // the enclosing type is not present
745 String matchName= qualifiedName;
746 int index= qualifiedName.indexOf('$');
747 boolean nested= false;
749 matchName= qualifiedName.substring(0, index);
752 int length= types.length;
753 for (int i= 0; i < length; i++) {
754 if (requestor.isCanceled())
756 IType memberType= types[i];
757 if (nameMatches(matchName, memberType, partialMatch))
759 seekQualifiedMemberTypes(qualifiedName.substring(index + 1, qualifiedName.length()), memberType, partialMatch, requestor, acceptFlags);
761 if (acceptType(memberType, acceptFlags)) requestor.acceptMemberType(memberType);