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.ICompilationUnit;
20 import net.sourceforge.phpdt.core.IJavaElement;
21 import net.sourceforge.phpdt.core.IJavaProject;
22 import net.sourceforge.phpdt.core.IPackageFragment;
23 import net.sourceforge.phpdt.core.IPackageFragmentRoot;
24 import net.sourceforge.phpdt.core.IType;
25 import net.sourceforge.phpdt.core.IWorkingCopy;
26 import net.sourceforge.phpdt.core.JavaCore;
27 import net.sourceforge.phpdt.core.JavaModelException;
28 import net.sourceforge.phpdt.internal.core.util.PerThreadObject;
29 import net.sourceforge.phpdt.internal.core.util.Util;
31 import org.eclipse.core.resources.IResource;
32 import org.eclipse.core.resources.IWorkspace;
33 import org.eclipse.core.resources.ResourcesPlugin;
34 import org.eclipse.core.runtime.IPath;
37 * A <code>NameLookup</code> provides name resolution within a Java project.
38 * The name lookup facility uses the project's classpath to prioritize the order
39 * in which package fragments are searched when resolving a name.
42 * Name lookup only returns a handle when the named element actually exists in
43 * the model; otherwise <code>null</code> is returned.
46 * There are two logical sets of methods within this interface. Methods which
47 * start with <code>find*</code> are intended to be convenience methods for
48 * quickly finding an element within another element; for instance, for finding
49 * a class within a package. The other set of methods all begin with
50 * <code>seek*</code>. These methods do comprehensive searches of the
51 * <code>IJavaProject</code> returning hits in real time through an
52 * <code>IJavaElementRequestor</code>.
55 public class NameLookup {
57 * Accept flag for specifying classes.
59 public static final int ACCEPT_CLASSES = 0x00000002;
62 * Accept flag for specifying interfaces.
64 public static final int ACCEPT_INTERFACES = 0x00000004;
67 * The <code>IPackageFragmentRoot</code>'s associated with the classpath
68 * of this NameLookup facility's project.
70 protected IPackageFragmentRoot[] fPackageFragmentRoots = null;
73 * Table that maps package names to lists of package fragments for all
74 * package fragments in the package fragment roots known by this name lookup
75 * facility. To allow > 1 package fragment with the same name, values are
76 * arrays of package fragments ordered as they appear on the classpath.
78 protected Map fPackageFragments;
81 * The <code>IWorkspace</code> that this NameLookup is configure within.
83 protected IWorkspace workspace;
86 * A map from compilation unit handles to units to look inside (compilation
87 * units or working copies). Allows working copies to take precedence over
88 * compilation units. The cache is a 2-level cache, first keyed by thread.
90 protected PerThreadObject unitsToLookInside = new PerThreadObject();
92 public NameLookup(IJavaProject project) throws JavaModelException {
93 configureFromProject(project);
99 * <li>the given type is an existing class and the flag's
100 * <code>ACCEPT_CLASSES</code> bit is on
101 * <li>the given type is an existing interface and the
102 * <code>ACCEPT_INTERFACES</code> bit is on
103 * <li>neither the <code>ACCEPT_CLASSES</code> or
104 * <code>ACCEPT_INTERFACES</code> bit is on
106 * Otherwise, false is returned.
108 protected boolean acceptType(IType type, int acceptFlags) {
109 if (acceptFlags == 0)
110 return true; // no flags, always accepted
112 if (type.isClass()) {
113 return (acceptFlags & ACCEPT_CLASSES) != 0;
115 return (acceptFlags & ACCEPT_INTERFACES) != 0;
117 } catch (JavaModelException npe) {
118 return false; // the class is not present, do not accept.
123 * Configures this <code>NameLookup</code> based on the info of the given
124 * <code>IJavaProject</code>.
126 * @throws JavaModelException
127 * if the <code>IJavaProject</code> has no classpath.
129 private void configureFromProject(IJavaProject project)
130 throws JavaModelException {
131 workspace = ResourcesPlugin.getWorkspace();
132 fPackageFragmentRoots = ((JavaProject) project)
133 .getAllPackageFragmentRoots();
134 fPackageFragments = new HashMap();
135 IPackageFragment[] frags = this.getPackageFragmentsInRoots(
136 fPackageFragmentRoots, project);
137 for (int i = 0; i < frags.length; i++) {
138 IPackageFragment fragment = frags[i];
139 IPackageFragment[] entry = (IPackageFragment[]) fPackageFragments
140 .get(fragment.getElementName());
142 entry = new IPackageFragment[1];
144 fPackageFragments.put(fragment.getElementName(), entry);
146 IPackageFragment[] copy = new IPackageFragment[entry.length + 1];
147 System.arraycopy(entry, 0, copy, 0, entry.length);
148 copy[entry.length] = fragment;
149 fPackageFragments.put(fragment.getElementName(), copy);
155 * Finds every type in the project whose simple name matches the prefix,
156 * informing the requestor of each hit. The requestor is polled for
157 * cancellation at regular intervals.
160 * The <code>partialMatch</code> argument indicates partial matches should
163 private void findAllTypes(String prefix, boolean partialMatch,
164 int acceptFlags, IJavaElementRequestor requestor) {
165 int count = fPackageFragmentRoots.length;
166 for (int i = 0; i < count; i++) {
167 if (requestor.isCanceled())
169 IPackageFragmentRoot root = fPackageFragmentRoots[i];
170 IJavaElement[] packages = null;
172 packages = root.getChildren();
173 } catch (JavaModelException npe) {
174 continue; // the root is not present, continue;
176 if (packages != null) {
177 for (int j = 0, packageCount = packages.length; j < packageCount; j++) {
178 if (requestor.isCanceled())
180 seekTypes(prefix, (IPackageFragment) packages[j],
181 partialMatch, acceptFlags, requestor);
188 * Returns the <code>ICompilationUnit</code> which defines the type named
189 * <code>qualifiedTypeName</code>, or <code>null</code> if none exists.
190 * The domain of the search is bounded by the classpath of the
191 * <code>IJavaProject</code> this <code>NameLookup</code> was obtained
194 * The name must be fully qualified (eg "java.lang.Object",
195 * "java.util.Hashtable$Entry")
197 public ICompilationUnit findCompilationUnit(String qualifiedTypeName) {
198 String pkgName = IPackageFragment.DEFAULT_PACKAGE_NAME;
199 String cuName = qualifiedTypeName;
201 int index = qualifiedTypeName.lastIndexOf('.');
203 pkgName = qualifiedTypeName.substring(0, index);
204 cuName = qualifiedTypeName.substring(index + 1);
206 index = cuName.indexOf('$');
208 cuName = cuName.substring(0, index);
210 cuName += ".java"; //$NON-NLS-1$
211 IPackageFragment[] frags = (IPackageFragment[]) fPackageFragments
214 for (int i = 0; i < frags.length; i++) {
215 IPackageFragment frag = frags[i];
216 // if (!(frag instanceof JarPackageFragment)) {
217 // ICompilationUnit cu= frag.getCompilationUnit(cuName);
218 // if (cu != null && cu.exists()) {
228 * Returns the package fragment whose path matches the given (absolute)
229 * path, or <code>null</code> if none exist. The domain of the search is
230 * bounded by the classpath of the <code>IJavaProject</code> this
231 * <code>NameLookup</code> was obtained from. The path can be: - internal
232 * to the workbench: "/Project/src" - external to the workbench:
233 * "c:/jdk/classes.zip/java/lang"
235 public IPackageFragment findPackageFragment(IPath path) {
236 if (!path.isAbsolute()) {
237 throw new IllegalArgumentException(Util.bind("path.mustBeAbsolute")); //$NON-NLS-1$
240 * this code should rather use the package fragment map to find the
241 * candidate package, then check if the respective enclosing root maps
242 * to the one on this given IPath.
244 IResource possibleFragment = workspace.getRoot().findMember(path);
245 if (possibleFragment == null) {
247 for (int i = 0; i < fPackageFragmentRoots.length; i++) {
248 IPackageFragmentRoot root = fPackageFragmentRoots[i];
249 if (!root.isExternal()) {
252 IPath rootPath = root.getPath();
253 int matchingCount = rootPath.matchingFirstSegments(path);
254 if (matchingCount != 0) {
255 String name = path.toOSString();
256 // + 1 is for the File.separatorChar
257 name = name.substring(rootPath.toOSString().length() + 1,
259 name = name.replace(File.separatorChar, '.');
260 IJavaElement[] list = null;
262 list = root.getChildren();
263 } catch (JavaModelException npe) {
264 continue; // the package fragment root is not present;
266 int elementCount = list.length;
267 for (int j = 0; j < elementCount; j++) {
268 IPackageFragment packageFragment = (IPackageFragment) list[j];
269 if (nameMatches(name, packageFragment, false)) {
270 return packageFragment;
276 IJavaElement fromFactory = JavaCore.create(possibleFragment);
277 if (fromFactory == null) {
280 if (fromFactory instanceof IPackageFragment) {
281 return (IPackageFragment) fromFactory;
282 } else if (fromFactory instanceof IJavaProject) {
283 // default package in a default root
284 JavaProject project = (JavaProject) fromFactory;
286 IClasspathEntry entry = project.getClasspathEntryFor(path);
288 IPackageFragmentRoot root = project
289 .getPackageFragmentRoot(project.getResource());
290 IPackageFragment[] pkgs = (IPackageFragment[]) fPackageFragments
291 .get(IPackageFragment.DEFAULT_PACKAGE_NAME);
295 for (int i = 0; i < pkgs.length; i++) {
296 if (pkgs[i].getParent().equals(root)) {
301 } catch (JavaModelException e) {
310 * Returns the package fragments whose name matches the given (qualified)
311 * name, or <code>null</code> if none exist.
313 * The name can be: - empty: "" - qualified: "pack.pack1.pack2"
315 * @param partialMatch
316 * partial name matches qualify when <code>true</code>, only
317 * exact name matches qualify when <code>false</code>
319 public IPackageFragment[] findPackageFragments(String name,
320 boolean partialMatch) {
321 int count = fPackageFragmentRoots.length;
323 name = name.toLowerCase();
324 for (int i = 0; i < count; i++) {
325 IPackageFragmentRoot root = fPackageFragmentRoots[i];
326 IJavaElement[] list = null;
328 list = root.getChildren();
329 } catch (JavaModelException npe) {
330 continue; // the package fragment root is not present;
332 int elementCount = list.length;
333 IPackageFragment[] result = new IPackageFragment[elementCount];
334 int resultLength = 0;
335 for (int j = 0; j < elementCount; j++) {
336 IPackageFragment packageFragment = (IPackageFragment) list[j];
337 if (nameMatches(name, packageFragment, true)) {
338 result[resultLength++] = packageFragment;
341 if (resultLength > 0) {
342 System.arraycopy(result, 0,
343 result = new IPackageFragment[resultLength], 0,
351 IPackageFragment[] fragments = (IPackageFragment[]) fPackageFragments
353 if (fragments != null) {
354 IPackageFragment[] result = new IPackageFragment[fragments.length];
355 int resultLength = 0;
356 for (int i = 0; i < fragments.length; i++) {
357 IPackageFragment packageFragment = fragments[i];
358 result[resultLength++] = packageFragment;
360 if (resultLength > 0) {
361 System.arraycopy(result, 0,
362 result = new IPackageFragment[resultLength], 0,
376 public IType findType(String typeName, String packageName,
377 boolean partialMatch, int acceptFlags) {
378 if (packageName == null) {
379 packageName = IPackageFragment.DEFAULT_PACKAGE_NAME;
381 JavaElementRequestor elementRequestor = new JavaElementRequestor();
382 seekPackageFragments(packageName, false, elementRequestor);
383 IPackageFragment[] packages = elementRequestor.getPackageFragments();
385 for (int i = 0, length = packages.length; i < length; i++) {
386 IType type = findType(typeName, packages[i], partialMatch,
395 * Returns all the package fragments found in the specified package fragment
396 * roots. Make sure the returned fragments have the given project as great
397 * parent. This ensures the name lookup will not refer to another project
398 * (through jar package fragment roots)
400 private IPackageFragment[] getPackageFragmentsInRoots(
401 IPackageFragmentRoot[] roots, IJavaProject project) {
403 // The following code assumes that all the roots have the given project
405 ArrayList frags = new ArrayList();
406 for (int i = 0; i < roots.length; i++) {
407 IPackageFragmentRoot root = roots[i];
409 IJavaElement[] children = root.getChildren();
412 * 2 jar package fragment roots can be equals but not belonging
413 * to the same project. As a result, they share the same element
414 * info. So this jar package fragment root could get the
415 * children of another jar package fragment root. The following
416 * code ensures that the children of this jar package fragment
417 * root have the given project as a great parent.
419 int length = children.length;
422 if (children[0].getParent().getParent().equals(project)) {
423 // the children have the right parent, simply add them to
425 for (int j = 0; j < length; j++) {
426 frags.add(children[j]);
429 // create a new handle with the root as the parent
430 for (int j = 0; j < length; j++) {
431 frags.add(root.getPackageFragment(children[j]
435 } catch (JavaModelException e) {
439 IPackageFragment[] fragments = new IPackageFragment[frags.size()];
440 frags.toArray(fragments);
445 * Returns the first type in the given package whose name matches the given
446 * (unqualified) name, or <code>null</code> if none exist. Specifying a
447 * <code>null</code> package will result in no matches. The domain of the
448 * search is bounded by the Java project from which this name lookup was
452 * the name of the type to find
454 * the package to search
455 * @param partialMatch
456 * partial name matches qualify when <code>true</code>, only
457 * exact name matches qualify when <code>false</code>
459 * a bit mask describing if classes, interfaces or both classes
460 * and interfaces are desired results. If no flags are specified,
461 * all types are returned.
463 * @see #ACCEPT_CLASSES
464 * @see #ACCEPT_INTERFACES
466 public IType findType(String name, IPackageFragment pkg,
467 boolean partialMatch, int acceptFlags) {
471 // Return first found (ignore duplicates).
472 // synchronized(JavaModelManager.getJavaModelManager()){
473 // SingleTypeRequestor typeRequestor = new SingleTypeRequestor();
474 // seekTypes(name, pkg, partialMatch, acceptFlags, typeRequestor);
475 // IType type= typeRequestor.getType();
482 * Returns the type specified by the qualified name, or <code>null</code>
483 * if none exist. The domain of the search is bounded by the Java project
484 * from which this name lookup was obtained.
487 * the name of the type to find
488 * @param partialMatch
489 * partial name matches qualify when <code>true</code>, only
490 * exact name matches qualify when <code>false</code>
492 * a bit mask describing if classes, interfaces or both classes
493 * and interfaces are desired results. If no flags are specified,
494 * all types are returned.
496 * @see #ACCEPT_CLASSES
497 * @see #ACCEPT_INTERFACES
499 public IType findType(String name, boolean partialMatch, int acceptFlags) {
500 int index = name.lastIndexOf('.');
501 String className = null, packageName = null;
503 packageName = IPackageFragment.DEFAULT_PACKAGE_NAME;
506 packageName = name.substring(0, index);
507 className = name.substring(index + 1);
509 return findType(className, packageName, partialMatch, acceptFlags);
513 * Returns true if the given element's name matches the specified
514 * <code>searchName</code>, otherwise false.
517 * The <code>partialMatch</code> argument indicates partial matches should
518 * be considered. NOTE: in partialMatch mode, the case will be ignored, and
519 * the searchName must already have been lowercased.
521 protected boolean nameMatches(String searchName, IJavaElement element,
522 boolean partialMatch) {
524 // partial matches are used in completion mode, thus case
526 return element.getElementName().toLowerCase()
527 .startsWith(searchName);
529 return element.getElementName().equals(searchName);
534 * Notifies the given requestor of all package fragments with the given
535 * name. Checks the requestor at regular intervals to see if the requestor
536 * has canceled. The domain of the search is bounded by the
537 * <code>IJavaProject</code> this <code>NameLookup</code> was obtained
540 * @param partialMatch
541 * partial name matches qualify when <code>true</code>; only
542 * exact name matches qualify when <code>false</code>
544 public void seekPackageFragments(String name, boolean partialMatch,
545 IJavaElementRequestor requestor) {
546 int count = fPackageFragmentRoots.length;
547 String matchName = partialMatch ? name.toLowerCase() : name;
548 for (int i = 0; i < count; i++) {
549 if (requestor.isCanceled())
551 IPackageFragmentRoot root = fPackageFragmentRoots[i];
552 IJavaElement[] list = null;
554 list = root.getChildren();
555 } catch (JavaModelException npe) {
556 continue; // this root package fragment is not present
558 int elementCount = list.length;
559 for (int j = 0; j < elementCount; j++) {
560 if (requestor.isCanceled())
562 IPackageFragment packageFragment = (IPackageFragment) list[j];
563 if (nameMatches(matchName, packageFragment, partialMatch))
564 requestor.acceptPackageFragment(packageFragment);
570 * Notifies the given requestor of all types (classes and interfaces) in the
571 * given package fragment with the given (unqualified) name. Checks the
572 * requestor at regular intervals to see if the requestor has canceled. If
573 * the given package fragment is <code>null</code>, all types in the
574 * project whose simple name matches the given name are found.
579 * The corresponding package fragment
580 * @param partialMatch
581 * partial name matches qualify when <code>true</code>; only
582 * exact name matches qualify when <code>false</code>
584 * a bit mask describing if classes, interfaces or both classes
585 * and interfaces are desired results. If no flags are specified,
586 * all types are returned.
588 * The requestor that collects the result
590 * @see #ACCEPT_CLASSES
591 * @see #ACCEPT_INTERFACES
593 public void seekTypes(String name, IPackageFragment pkg,
594 boolean partialMatch, int acceptFlags,
595 IJavaElementRequestor requestor) {
597 String matchName = partialMatch ? name.toLowerCase() : name;
598 if (matchName.indexOf('.') >= 0) { // looks for member type A.B
599 matchName = matchName.replace('.', '$');
602 findAllTypes(matchName, partialMatch, acceptFlags, requestor);
605 IPackageFragmentRoot root = (IPackageFragmentRoot) pkg.getParent();
607 int packageFlavor = root.getKind();
608 switch (packageFlavor) {
609 // case IPackageFragmentRoot.K_BINARY :
610 // seekTypesInBinaryPackage(matchName, pkg, partialMatch,
611 // acceptFlags, requestor);
613 case IPackageFragmentRoot.K_SOURCE:
614 seekTypesInSourcePackage(matchName, pkg, partialMatch,
615 acceptFlags, requestor);
620 } catch (JavaModelException e) {
626 * Performs type search in a binary package.
628 // protected void seekTypesInBinaryPackage(String name, IPackageFragment
629 // pkg, boolean partialMatch, int acceptFlags, IJavaElementRequestor
631 // IClassFile[] classFiles= null;
633 // classFiles= pkg.getClassFiles();
634 // } catch (JavaModelException npe) {
635 // return; // the package is not present
637 // int length= classFiles.length;
639 // String unqualifiedName= name;
640 // int index= name.lastIndexOf('$');
641 // if (index != -1) {
642 // //the type name of the inner type
643 // unqualifiedName= name.substring(index + 1, name.length());
644 // // unqualifiedName is empty if the name ends with a '$' sign.
645 // // See http://dev.eclipse.org/bugs/show_bug.cgi?id=14642
646 // if ((unqualifiedName.length() > 0 &&
647 // Character.isDigit(unqualifiedName.charAt(0))) || unqualifiedName.length()
649 // unqualifiedName = name;
652 // String matchName= partialMatch ? name.toLowerCase() : name;
653 // for (int i= 0; i < length; i++) {
654 // if (requestor.isCanceled())
656 // IClassFile classFile= classFiles[i];
657 // String elementName = classFile.getElementName();
658 // if (partialMatch) elementName = elementName.toLowerCase();
661 // * Must use startWith because matchName will never have the
662 // * extension ".class" and the elementName always will.
664 // if (elementName.startsWith(matchName)) {
667 // type= classFile.getType();
668 // } catch (JavaModelException npe) {
669 // continue; // the classFile is not present
671 // if (!partialMatch || (type.getElementName().length() > 0 &&
672 // !Character.isDigit(type.getElementName().charAt(0)))) { //not an
674 // if (nameMatches(unqualifiedName, type, partialMatch) && acceptType(type,
676 // requestor.acceptType(type);
682 * Performs type search in a source package.
684 protected void seekTypesInSourcePackage(String name, IPackageFragment pkg,
685 boolean partialMatch, int acceptFlags,
686 IJavaElementRequestor requestor) {
687 ICompilationUnit[] compilationUnits = null;
689 compilationUnits = pkg.getCompilationUnits();
690 } catch (JavaModelException npe) {
691 return; // the package is not present
693 int length = compilationUnits.length;
694 String matchName = name;
695 int index = name.indexOf('$');
696 boolean potentialMemberType = false;
697 String potentialMatchName = null;
699 // the compilation unit name of the inner type
700 potentialMatchName = name.substring(0, index);
701 potentialMemberType = true;
705 * In the following, matchName will never have the extension ".java" and
706 * the compilationUnits always will. So add it if we're looking for an
709 String unitName = partialMatch ? matchName.toLowerCase() : matchName
710 + ".java"; //$NON-NLS-1$
711 String potentialUnitName = null;
712 if (potentialMemberType) {
713 potentialUnitName = partialMatch ? potentialMatchName.toLowerCase()
714 : potentialMatchName + ".java"; //$NON-NLS-1$
717 for (int i = 0; i < length; i++) {
718 if (requestor.isCanceled())
720 ICompilationUnit compilationUnit = compilationUnits[i];
722 // unit to look inside
723 ICompilationUnit unitToLookInside = null;
724 Map workingCopies = (Map) this.unitsToLookInside.getCurrent();
725 if (workingCopies != null
726 && (unitToLookInside = (ICompilationUnit) workingCopies
727 .get(compilationUnit)) != null) {
728 compilationUnit = unitToLookInside;
730 if ((unitToLookInside != null && !potentialMemberType)
731 || nameMatches(unitName, compilationUnit, partialMatch)) {
732 IType[] types = null;
734 types = compilationUnit.getTypes();
735 } catch (JavaModelException npe) {
736 continue; // the compilation unit is not present
738 int typeLength = types.length;
739 for (int j = 0; j < typeLength; j++) {
740 if (requestor.isCanceled())
742 IType type = types[j];
743 if (nameMatches(matchName, type, partialMatch)) {
744 if (acceptType(type, acceptFlags))
745 requestor.acceptType(type);
748 } else if (potentialMemberType
749 && nameMatches(potentialUnitName, compilationUnit,
751 IType[] types = null;
753 types = compilationUnit.getTypes();
754 } catch (JavaModelException npe) {
755 continue; // the compilation unit is not present
757 int typeLength = types.length;
758 for (int j = 0; j < typeLength; j++) {
759 if (requestor.isCanceled())
761 IType type = types[j];
762 if (nameMatches(potentialMatchName, type, partialMatch)) {
763 seekQualifiedMemberTypes(name.substring(index + 1, name
764 .length()), type, partialMatch, requestor,
774 * Remembers a set of compilation units that will be looked inside when
775 * looking up a type. If they are working copies, they take precedence of
776 * their compilation units. <code>null</code> means that no special
777 * compilation units should be used.
779 public void setUnitsToLookInside(IWorkingCopy[] unitsToLookInside) {
781 if (unitsToLookInside == null) {
782 this.unitsToLookInside.setCurrent(null);
784 HashMap workingCopies = new HashMap();
785 this.unitsToLookInside.setCurrent(workingCopies);
786 for (int i = 0, length = unitsToLookInside.length; i < length; i++) {
787 IWorkingCopy unitToLookInside = unitsToLookInside[i];
788 ICompilationUnit original = (ICompilationUnit) unitToLookInside
789 .getOriginalElement();
790 if (original != null) {
791 workingCopies.put(original, unitToLookInside);
793 workingCopies.put(unitToLookInside, unitToLookInside);
800 * Notifies the given requestor of all types (classes and interfaces) in the
801 * given type with the given (possibly qualified) name. Checks the requestor
802 * at regular intervals to see if the requestor has canceled.
804 * @param partialMatch
805 * partial name matches qualify when <code>true</code>, only
806 * exact name matches qualify when <code>false</code>
808 protected void seekQualifiedMemberTypes(String qualifiedName, IType type,
809 boolean partialMatch, IJavaElementRequestor requestor,
813 IType[] types = null;
815 types = type.getTypes();
816 } catch (JavaModelException npe) {
817 return; // the enclosing type is not present
819 String matchName = qualifiedName;
820 int index = qualifiedName.indexOf('$');
821 boolean nested = false;
823 matchName = qualifiedName.substring(0, index);
826 int length = types.length;
827 for (int i = 0; i < length; i++) {
828 if (requestor.isCanceled())
830 IType memberType = types[i];
831 if (nameMatches(matchName, memberType, partialMatch))
833 seekQualifiedMemberTypes(qualifiedName.substring(index + 1,
834 qualifiedName.length()), memberType, partialMatch,
835 requestor, acceptFlags);
837 if (acceptType(memberType, acceptFlags))
838 requestor.acceptMemberType(memberType);