/*******************************************************************************
* Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.wst.jsdt.internal.core;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.wst.jsdt.core.IClassFile;
import org.eclipse.wst.jsdt.core.IField;
import org.eclipse.wst.jsdt.core.IFunction;
import org.eclipse.wst.jsdt.core.IIncludePathEntry;
import org.eclipse.wst.jsdt.core.IInitializer;
import org.eclipse.wst.jsdt.core.IJavaScriptElement;
import org.eclipse.wst.jsdt.core.IJavaScriptProject;
import org.eclipse.wst.jsdt.core.IJavaScriptUnit;
import org.eclipse.wst.jsdt.core.IOpenable;
import org.eclipse.wst.jsdt.core.IPackageFragment;
import org.eclipse.wst.jsdt.core.IPackageFragmentRoot;
import org.eclipse.wst.jsdt.core.IType;
import org.eclipse.wst.jsdt.core.ITypeRoot;
import org.eclipse.wst.jsdt.core.JavaScriptCore;
import org.eclipse.wst.jsdt.core.JavaScriptModelException;
import org.eclipse.wst.jsdt.core.compiler.CharOperation;
import org.eclipse.wst.jsdt.core.infer.IInferenceFile;
import org.eclipse.wst.jsdt.core.infer.InferrenceManager;
import org.eclipse.wst.jsdt.core.infer.InferrenceProvider;
import org.eclipse.wst.jsdt.core.infer.ResolutionConfiguration;
import org.eclipse.wst.jsdt.core.search.IJavaScriptSearchConstants;
import org.eclipse.wst.jsdt.core.search.IJavaScriptSearchScope;
import org.eclipse.wst.jsdt.core.search.SearchPattern;
import org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode;
import org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.wst.jsdt.internal.compiler.env.AccessRestriction;
import org.eclipse.wst.jsdt.internal.compiler.env.AccessRuleSet;
import org.eclipse.wst.jsdt.internal.compiler.lookup.Binding;
import org.eclipse.wst.jsdt.internal.compiler.lookup.CompilationUnitScope;
import org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.wst.jsdt.internal.compiler.lookup.SourceTypeBinding;
import org.eclipse.wst.jsdt.internal.compiler.parser.ScannerHelper;
import org.eclipse.wst.jsdt.internal.compiler.util.SuffixConstants;
import org.eclipse.wst.jsdt.internal.core.search.BasicSearchEngine;
import org.eclipse.wst.jsdt.internal.core.search.IRestrictedAccessBindingRequestor;
import org.eclipse.wst.jsdt.internal.core.util.HandleFactory;
import org.eclipse.wst.jsdt.internal.core.util.HashtableOfArrayToObject;
import org.eclipse.wst.jsdt.internal.core.util.Messages;
import org.eclipse.wst.jsdt.internal.core.util.Util;
/**
* A <code>NameLookup</code> provides name resolution within a Java project.
* The name lookup facility uses the project's classpath to prioritize the
* order in which package fragments are searched when resolving a name.
*
* <p>Name lookup only returns a handle when the named element actually
* exists in the model; otherwise <code>null</code> is returned.
*
* <p>There are two logical sets of methods within this interface. Methods
* which start with <code>find*</code> are intended to be convenience methods for quickly
* finding an element within another element; for instance, for finding a class within a
* package. The other set of methods all begin with <code>seek*</code>. These methods
* do comprehensive searches of the <code>IJavaScriptProject</code> returning hits
* in real time through an <code>IJavaElementRequestor</code>.
*
*/
public class NameLookup implements SuffixConstants {
public static class Answer {
public IType type;
public Object element;
AccessRestriction restriction;
Answer(IType type, AccessRestriction restriction) {
this.type = type;
this.restriction = restriction;
}
Answer(Object element, AccessRestriction restriction) {
this.element = element;
this.restriction = restriction;
}
public boolean ignoreIfBetter() {
return this.restriction != null && this.restriction.ignoreIfBetter();
}
/*
* Returns whether this answer is better than the other awswer.
* (accessible is better than discouraged, which is better than
* non-accessible)
*/
public boolean isBetter(Answer otherAnswer) {
if (otherAnswer == null) return true;
if (this.restriction == null) return true;
return otherAnswer.restriction != null
&& this.restriction.getProblemId() < otherAnswer.restriction.getProblemId();
}
}
// TODO (jerome) suppress the accept flags (qualified name is sufficient to find a type)
/**
* Accept flag for specifying classes.
*/
public static final int ACCEPT_CLASSES = ASTNode.Bit2;
/**
* Accept flag for specifying interfaces.
*/
public static final int ACCEPT_INTERFACES = ASTNode.Bit3;
/**
* Accept flag for specifying enums.
*/
public static final int ACCEPT_ENUMS = ASTNode.Bit4;
/**
* Accept flag for specifying annotations.
*/
public static final int ACCEPT_ANNOTATIONS = ASTNode.Bit5;
/*
* Accept flag for all kinds of types
*/
public static final int ACCEPT_ALL = ACCEPT_CLASSES | ACCEPT_INTERFACES | ACCEPT_ENUMS | ACCEPT_ANNOTATIONS;
public static boolean VERBOSE = false;
private static final IType[] NO_TYPES = {};
private static final IJavaScriptElement[] NO_BINDINGS = {};
private boolean searchFiles=true;
/**
* The <code>IPackageFragmentRoot</code>'s associated
* with the classpath of this NameLookup facility's
* project.
*/
protected IPackageFragmentRoot[] packageFragmentRoots;
/**
* Table that maps package names to lists of package fragment roots
* that contain such a package known by this name lookup facility.
* To allow > 1 package fragment with the same name, values are
* arrays of package fragment roots ordered as they appear on the
* classpath.
* Note if the list is of size 1, then the IPackageFragmentRoot object
* replaces the array.
*/
protected HashtableOfArrayToObject packageFragments;
/**
* Reverse map from root path to corresponding resolved CP entry
* (so as to be able to figure inclusion/exclusion rules)
*/
protected Map rootToResolvedEntries;
/**
* A map from package handles to a map from type name to an IType or an IType[].
* Allows working copies to take precedence over compilation units.
*/
protected HashMap typesInWorkingCopies;
protected HashMap[] bindingsInWorkingCopies;
public long timeSpentInSeekTypesInSourcePackage = 0;
public long timeSpentInSeekTypesInBinaryPackage = 0;
protected HashSet acceptedCUs=new HashSet();
private IJavaScriptUnit[] workingCopies;
IRestrictedAccessBindingRequestor restrictedRequestor;
public NameLookup(
IPackageFragmentRoot[] packageFragmentRoots,
HashtableOfArrayToObject packageFragments,
IJavaScriptUnit[] workingCopies,
Map rootToResolvedEntries) {
long start = -1;
if (VERBOSE) {
Util.verbose(" BUILDING NameLoopkup"); //$NON-NLS-1$
Util.verbose(" -> pkg roots size: " + (packageFragmentRoots == null ? 0 : packageFragmentRoots.length)); //$NON-NLS-1$
Util.verbose(" -> pkgs size: " + (packageFragments == null ? 0 : packageFragments.size())); //$NON-NLS-1$
Util.verbose(" -> working copy size: " + (workingCopies == null ? 0 : workingCopies.length)); //$NON-NLS-1$
start = System.currentTimeMillis();
}
// this.restrictedRequestor=restrictedRequestor;
//this.restrictToLanguage=restrictToLanguage;
this.packageFragmentRoots = packageFragmentRoots;
if (workingCopies == null) {
this.packageFragments = packageFragments;
} else {
// clone tables as we're adding packages from working copies
try {
this.packageFragments = (HashtableOfArrayToObject) packageFragments.clone();
} catch (CloneNotSupportedException e1) {
// ignore (implementation of HashtableOfArrayToObject supports cloning)
}
this.typesInWorkingCopies = new HashMap();
this.bindingsInWorkingCopies = new HashMap[Binding.NUMBER_BASIC_BINDING];
for (int j = 0; j <Binding.NUMBER_BASIC_BINDING; j++) {
this.bindingsInWorkingCopies[j] = new HashMap();
}
this.workingCopies=workingCopies;
for (int i = 0, length = workingCopies.length; i < length; i++) {
IJavaScriptUnit workingCopy = workingCopies[i];
try {
IType[] types = workingCopy.getTypes();
int typeLength = types.length;
if (typeLength == 0) {
String typeName = Util.getNameWithoutJavaLikeExtension(workingCopy.getElementName());
this.typesInWorkingCopies.put(typeName, NO_TYPES);
} else {
for (int j = 0; j < typeLength; j++) {
IType type = types[j];
String typeName = type.getElementName();
Object existing = this.typesInWorkingCopies.get(typeName);
if (existing == null) {
this.typesInWorkingCopies.put(typeName, type);
} else if (existing instanceof IType) {
this.typesInWorkingCopies.put(typeName, new IType[] {(IType) existing, type});
} else {
IType[] existingTypes = (IType[]) existing;
int existingTypeLength = existingTypes.length;
System.arraycopy(existingTypes, 0, existingTypes = new IType[existingTypeLength+1], 0, existingTypeLength);
existingTypes[existingTypeLength] = type;
this.typesInWorkingCopies.put(typeName, existingTypes);
}
}
}
addWorkingCopyBindings(types, this.bindingsInWorkingCopies[Binding.TYPE]);
addWorkingCopyBindings(workingCopy.getFields(), this.bindingsInWorkingCopies[Binding.VARIABLE]);
addWorkingCopyBindings(workingCopy.getFields(), this.bindingsInWorkingCopies[Binding.LOCAL]);
addWorkingCopyBindings(workingCopy.getFunctions(), this.bindingsInWorkingCopies[Binding.METHOD]);
} catch (JavaScriptModelException e) {
// working copy doesn't exist -> ignore
}
// add root of package fragment to cache
PackageFragment pkg = (PackageFragment) workingCopy.getParent();
IPackageFragmentRoot root = (IPackageFragmentRoot) pkg.getParent();
String[] pkgName = pkg.names;
Object existing = this.packageFragments.get(pkgName);
if (existing == null || existing == JavaProjectElementInfo.NO_ROOTS) {
this.packageFragments.put(pkgName, root);
// ensure super packages (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=119161)
// are also in the map
JavaProjectElementInfo.addSuperPackageNames(pkgName, this.packageFragments);
} else {
if (existing instanceof PackageFragmentRoot) {
if (!existing.equals(root))
this.packageFragments.put(pkgName, new IPackageFragmentRoot[] {(PackageFragmentRoot) existing, root});
} else {
IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) existing;
int rootLength = roots.length;
boolean containsRoot = false;
for (int j = 0; j < rootLength; j++) {
if (roots[j].equals(root)) {
containsRoot = true;
break;
}
}
if (containsRoot) {
System.arraycopy(roots, 0, roots = new IPackageFragmentRoot[rootLength+1], 0, rootLength);
roots[rootLength] = root;
this.packageFragments.put(pkgName, roots);
}
}
}
}
}
this.rootToResolvedEntries = rootToResolvedEntries;
if (VERBOSE) {
Util.verbose(" -> spent: " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
public void setRestrictedAccessRequestor(IRestrictedAccessBindingRequestor restrictedRequestor) {
this.restrictedRequestor=restrictedRequestor;
}
protected IRestrictedAccessBindingRequestor getRestrictedAccessRequestor() {
if(this.restrictedRequestor==null) {
this.restrictedRequestor=new IRestrictedAccessBindingRequestor() {
ArrayList foundPaths=new ArrayList();
String excludePath;
public void setExcludePath(String excludePath) {
this.excludePath = excludePath;
}
public boolean acceptBinding(int type,int modifiers, char[] packageName,
char[] simpleTypeName,
String path, AccessRestriction access) {
if (excludePath!=null && path.equals(excludePath))
return false;
foundPaths.add(path);
return true;
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.internal.core.search.IRestrictedAccessBindingRequestor#getFoundPaths()
*/
public String getFoundPath() {
return foundPaths.size()>0?(String)foundPaths.get(0):null;
}
public void reset() {
foundPaths.clear();
}
public ArrayList getFoundPaths()
{
return foundPaths;
}
};
}
return this.restrictedRequestor;
}
private void addWorkingCopyBindings(IJavaScriptElement [] elements, HashMap bindingsMap)
{
for (int j = 0; j < elements.length; j++) {
IJavaScriptElement element = elements[j];
String elementName = element.getElementName();
Object existing = bindingsMap.get(elementName);
if (existing == null) {
bindingsMap.put(elementName, element);
} else if (existing instanceof IJavaScriptElement) {
bindingsMap.put(elementName, new IJavaScriptElement[] {(IJavaScriptElement) existing, element});
} else {
IJavaScriptElement[] existingElements = (IJavaScriptElement[]) existing;
int existingElementsLength = existingElements.length;
System.arraycopy(existingElements, 0, existingElements = new IJavaScriptElement[existingElementsLength+1], 0, existingElementsLength);
existingElements[existingElementsLength] = element;
bindingsMap.put(elementName, existingElements);
}
}
}
/**
* Returns true if:<ul>
* <li>the given type is an existing class and the flag's <code>ACCEPT_CLASSES</code>
* bit is on
* <li>the given type is an existing interface and the <code>ACCEPT_INTERFACES</code>
* bit is on
* <li>neither the <code>ACCEPT_CLASSES</code> or <code>ACCEPT_INTERFACES</code>
* bit is on
* </ul>
* Otherwise, false is returned.
*/
protected boolean acceptType(IType type, int acceptFlags, boolean isSourceType) {
if (!type.exists())
return false;
if (acceptFlags == 0 || acceptFlags == ACCEPT_ALL)
return true; // no flags or all flags, always accepted
try {
int kind = TypeDeclaration.kind(((SourceTypeElementInfo) ((SourceType) type).getElementInfo()).getModifiers());
// int kind = isSourceType
// ? TypeDeclaration.kind(((SourceTypeElementInfo) ((SourceType) type).getElementInfo()).getModifiers())
// : TypeDeclaration.kind(((IBinaryType) ((BinaryType) type).getElementInfo()).getModifiers());
switch (kind) {
case TypeDeclaration.CLASS_DECL :
return (acceptFlags & ACCEPT_CLASSES) != 0;
default:
//case IGenericType.ANNOTATION_TYPE :
return (acceptFlags & ACCEPT_ANNOTATIONS) != 0;
}
} catch (JavaScriptModelException npe) {
return false; // the class is not present, do not accept.
}
}
protected boolean doAcceptBinding(IJavaScriptElement element, int bindingType, boolean isSourceType,IJavaElementRequestor requestor) {
switch (bindingType)
{
case Binding.FIELD | Binding.METHOD:
if (element instanceof IFunction)
{
requestor.acceptMethod((IFunction)element);
return true;
}
if (element instanceof IField)
{
requestor.acceptField( (IField)element);
return true;
}
return false;
case Binding.FIELD:
case Binding.VARIABLE:
if (element instanceof IField)
{
requestor.acceptField( (IField)element);
return true;
}
return false;
case Binding.METHOD:
if (element instanceof IFunction)
{
requestor.acceptMethod((IFunction)element);
return true;
}
case Binding.TYPE:
if (element instanceof IType)
{
requestor.acceptType((IType)element);
return true;
}
}
return false;
}
/**
* Finds every type in the project whose simple name matches
* the prefix, informing the requestor of each hit. The requestor
* is polled for cancellation at regular intervals.
*
* <p>The <code>partialMatch</code> argument indicates partial matches
* should be considered.
*/
private void findAllTypes(String prefix, boolean partialMatch, int acceptFlags, IJavaElementRequestor requestor) {
int count= this.packageFragmentRoots.length;
for (int i= 0; i < count; i++) {
if (requestor.isCanceled())
return;
IPackageFragmentRoot root= this.packageFragmentRoots[i];
IJavaScriptElement[] packages= null;
try {
packages= root.getChildren();
} catch (JavaScriptModelException npe) {
continue; // the root is not present, continue;
}
if (packages != null) {
for (int j= 0, packageCount= packages.length; j < packageCount; j++) {
if (requestor.isCanceled())
return;
seekTypes(prefix, (IPackageFragment) packages[j], partialMatch, acceptFlags, requestor);
}
}
}
}
private void findAllBindings(String prefix,int bindingType, boolean partialMatch, int acceptFlags, IJavaElementRequestor requestor) {
int count= this.packageFragmentRoots.length;
for (int i= 0; i < count; i++) {
if (requestor.isCanceled())
return;
IPackageFragmentRoot root= this.packageFragmentRoots[i];
IJavaScriptElement[] packages= null;
try {
packages= root.getChildren();
} catch (JavaScriptModelException npe) {
continue; // the root is not present, continue;
}
if (packages != null) {
for (int j= 0, packageCount= packages.length; j < packageCount; j++) {
if (requestor.isCanceled())
return;
seekBindings(prefix,bindingType, (IPackageFragment) packages[j], partialMatch, acceptFlags, requestor);
}
}
}
}
/**
* Returns the <code>IJavaScriptUnit</code> which defines the type
* named <code>qualifiedTypeName</code>, or <code>null</code> if
* none exists. The domain of the search is bounded by the classpath
* of the <code>IJavaScriptProject</code> this <code>NameLookup</code> was
* obtained from.
* <p>
* The name must be fully qualified (eg "java.lang.Object", "java.util.Hashtable$Entry")
*/
public ITypeRoot findCompilationUnit(String qualifiedTypeName) {
String[] pkgName = CharOperation.NO_STRINGS;
String cuName = qualifiedTypeName;
int index= qualifiedTypeName.lastIndexOf('.');
if (index != -1) {
pkgName= Util.splitOn('.', qualifiedTypeName, 0, index);
cuName= qualifiedTypeName.substring(index + 1);
}
cuName=cuName.replace(CompilationUnitScope.FILENAME_DOT_SUBSTITUTION, '.');
index= cuName.indexOf('$');
if (index != -1) {
cuName= cuName.substring(0, index);
}
Object value = this.packageFragments.get(pkgName);
if (value != null) {
if (value instanceof PackageFragmentRoot) {
return findCompilationUnit(pkgName, cuName, (PackageFragmentRoot) value);
} else {
IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) value;
for (int i= 0; i < roots.length; i++) {
PackageFragmentRoot root= (PackageFragmentRoot) roots[i];
ITypeRoot cu = findCompilationUnit(pkgName, cuName, root);
if (cu != null)
return cu;
}
}
}
return null;
}
private ITypeRoot findCompilationUnit(String[] pkgName, String cuName, PackageFragmentRoot root) {
if (!root.isArchive()) {
IPackageFragment pkg = root.getPackageFragment(pkgName);
try {
IJavaScriptUnit[] cus = pkg.getJavaScriptUnits();
for (int j = 0, length = cus.length; j < length; j++) {
IJavaScriptUnit cu = cus[j];
if (Util.equalsIgnoreJavaLikeExtension(cu.getElementName(), cuName))
return cu;
}
IClassFile[] classFiles = pkg.getClassFiles();
for (int j = 0, length = classFiles.length; j < length; j++) {
IClassFile cu = classFiles[j];
if (Util.equalsIgnoreJavaLikeExtension(cu.getElementName(), cuName))
return cu;
}
} catch (JavaScriptModelException e) {
// pkg does not exist
// -> try next package
}
}
return null;
}
/**
* Returns the package fragment whose path matches the given
* (absolute) path, or <code>null</code> if none exist. The domain of
* the search is bounded by the classpath of the <code>IJavaScriptProject</code>
* this <code>NameLookup</code> was obtained from.
* The path can be:
* - internal to the workbench: "/Project/src"
* - external to the workbench: "c:/jdk/classes.zip/java/lang"
*/
public IPackageFragment findPackageFragment(IPath path) {
if (!path.isAbsolute()) {
throw new IllegalArgumentException(Messages.path_mustBeAbsolute);
}
/*
* TODO (jerome) this code should rather use the package fragment map to find the candidate package, then
* check if the respective enclosing root maps to the one on this given IPath.
*/
IResource possibleFragment = ResourcesPlugin.getWorkspace().getRoot().findMember(path);
if (possibleFragment == null) {
//external jar
for (int i = 0; i < this.packageFragmentRoots.length; i++) {
IPackageFragmentRoot root = this.packageFragmentRoots[i];
if (!root.isExternal()) {
continue;
}
IPath rootPath = root.getPath();
int matchingCount = rootPath.matchingFirstSegments(path);
if (matchingCount != 0) {
String name = path.toOSString();
// + 1 is for the File.separatorChar
name = name.substring(rootPath.toOSString().length() + 1, name.length());
name = name.replace(File.separatorChar, '.');
IJavaScriptElement[] list = null;
try {
list = root.getChildren();
} catch (JavaScriptModelException npe) {
continue; // the package fragment root is not present;
}
int elementCount = list.length;
for (int j = 0; j < elementCount; j++) {
IPackageFragment packageFragment = (IPackageFragment) list[j];
if (nameMatches(name, packageFragment, false)) {
return packageFragment;
}
}
}
}
} else {
IJavaScriptElement fromFactory = JavaScriptCore.create(possibleFragment);
if (fromFactory == null) {
return null;
}
switch (fromFactory.getElementType()) {
case IJavaScriptElement.PACKAGE_FRAGMENT:
return (IPackageFragment) fromFactory;
case IJavaScriptElement.JAVASCRIPT_PROJECT:
// default package in a default root
JavaProject project = (JavaProject) fromFactory;
try {
IIncludePathEntry entry = project.getClasspathEntryFor(path);
if (entry != null) {
IPackageFragmentRoot root =
project.getPackageFragmentRoot(project.getResource());
Object defaultPkgRoot = this.packageFragments.get(CharOperation.NO_STRINGS);
if (defaultPkgRoot == null) {
return null;
}
if (defaultPkgRoot instanceof PackageFragmentRoot && defaultPkgRoot.equals(root))
return ((PackageFragmentRoot) root).getPackageFragment(CharOperation.NO_STRINGS);
else {
IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) defaultPkgRoot;
for (int i = 0; i < roots.length; i++) {
if (roots[i].equals(root)) {
return ((PackageFragmentRoot) root).getPackageFragment(CharOperation.NO_STRINGS);
}
}
}
}
} catch (JavaScriptModelException e) {
return null;
}
return null;
case IJavaScriptElement.PACKAGE_FRAGMENT_ROOT:
return ((PackageFragmentRoot)fromFactory).getPackageFragment(CharOperation.NO_STRINGS);
}
}
return null;
}
/**
* Returns the package fragments whose name matches the given
* (qualified) name, or <code>null</code> if none exist.
*
* The name can be:
* <ul>
* <li>empty: ""</li>
* <li>qualified: "pack.pack1.pack2"</li>
* </ul>
* @param partialMatch partial name matches qualify when <code>true</code>,
* only exact name matches qualify when <code>false</code>
*/
public IPackageFragment[] findPackageFragments(String name, boolean partialMatch) {
return findPackageFragments(name, partialMatch, false);
}
/**
* Returns the package fragments whose name matches the given
* (qualified) name or pattern, or <code>null</code> if none exist.
*
* The name can be:
* <ul>
* <li>empty: ""</li>
* <li>qualified: "pack.pack1.pack2"</li>
* <li>a pattern: "pack.*.util"</li>
* </ul>
* @param partialMatch partial name matches qualify when <code>true</code>,
* @param patternMatch <code>true</code> when the given name might be a pattern,
* <code>false</code> otherwise.
*/
public IPackageFragment[] findPackageFragments(String name, boolean partialMatch, boolean patternMatch) {
ArrayList fragRootChildren = new ArrayList();
for (int i = 0; i < this.packageFragmentRoots.length; i++) {
IJavaScriptElement[] children;
try {
children = packageFragmentRoots[i].getChildren();
for (int j = 0; j < children.length; j++) {
IPackageFragment packageFragment = (IPackageFragment)children[j];
if(packageFragment!=null && packageFragment.getElementName().equals(name))
fragRootChildren.add((packageFragment));
}
} catch (JavaScriptModelException e) {}
}
return (IPackageFragment[])fragRootChildren.toArray(new IPackageFragment[fragRootChildren.size()]);
// if (partialMatch) {
// String[] splittedName = Util.splitOn('.', name, 0, name.length());
// IPackageFragment[] oneFragment = null;
// ArrayList pkgs = null;
// Object[][] keys = this.packageFragments.keyTable;
// for (int i = 0, length = keys.length; i < length; i++) {
// String[] pkgName = (String[]) keys[i];
// if (pkgName != null && Util.startsWithIgnoreCase(pkgName, splittedName)) {
// Object value = this.packageFragments.valueTable[i];
// if (value instanceof PackageFragmentRoot) {
// IPackageFragment pkg = ((PackageFragmentRoot) value).getPackageFragment(pkgName);
// if (oneFragment == null) {
// oneFragment = new IPackageFragment[] {pkg};
// } else {
// if (pkgs == null) {
// pkgs = new ArrayList();
// pkgs.add(oneFragment[0]);
// }
// pkgs.add(pkg);
// }
// } else {
// IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) value;
// for (int j = 0, length2 = roots.length; j < length2; j++) {
// PackageFragmentRoot root = (PackageFragmentRoot) roots[j];
// IPackageFragment pkg = root.getPackageFragment(pkgName);
// if (oneFragment == null) {
// oneFragment = new IPackageFragment[] {pkg};
// } else {
// if (pkgs == null) {
// pkgs = new ArrayList();
// pkgs.add(oneFragment[0]);
// }
// pkgs.add(pkg);
// }
// }
// }
// }
// }
// if (pkgs == null) return oneFragment;
// int resultLength = pkgs.size();
// IPackageFragment[] result = new IPackageFragment[resultLength];
// pkgs.toArray(result);
// return result;
// } else {
// String[] splittedName = (name.length()>0)? new String[]{name}: new String[0];//Util.splitOn('.', name, 0, name.length());
// Object value = this.packageFragments.get(splittedName);
// if (value==null)
// value=this.packageFragments.get(new String[]{name});
// if (value == null)
// return null;
// if (value instanceof PackageFragmentRoot) {
// return new IPackageFragment[] {((PackageFragmentRoot) value).getPackageFragment(splittedName)};
// } else {
// IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) value;
// IPackageFragment[] result = new IPackageFragment[roots.length];
// for (int i= 0; i < roots.length; i++) {
// result[i] = ((PackageFragmentRoot) roots[i]).getPackageFragment(splittedName);
// }
// return result;
// }
// }
}
/*
* Find secondary type for a project.
*/
private IType findSecondaryType(String packageName, String typeName, IJavaScriptProject project, boolean waitForIndexes, IProgressMonitor monitor) {
if (JavaModelManager.VERBOSE) {
Util.verbose("NameLookup FIND SECONDARY TYPES:"); //$NON-NLS-1$
Util.verbose(" -> pkg name: " + packageName); //$NON-NLS-1$
Util.verbose(" -> type name: " + typeName); //$NON-NLS-1$
Util.verbose(" -> project: "+project.getElementName()); //$NON-NLS-1$
}
JavaModelManager manager = JavaModelManager.getJavaModelManager();
try {
IJavaScriptProject javaProject = project;
Map secondaryTypePaths = manager.secondaryTypes(javaProject, waitForIndexes, monitor);
if (secondaryTypePaths.size() > 0) {
Map types = (Map) secondaryTypePaths.get(packageName==null?"":packageName); //$NON-NLS-1$
if (types != null && types.size() > 0) {
IType type = (IType) types.get(typeName);
if (type != null) {
if (JavaModelManager.VERBOSE) {
Util.verbose(" -> type: " + type.getElementName()); //$NON-NLS-1$
}
return type;
}
}
}
}
catch (JavaScriptModelException jme) {
// give up
}
return null;
}
/**
* Find type considering secondary types but without waiting for indexes.
* It means that secondary types may be not found under certain circumstances...
* @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=118789"
*/
public Answer findType(String typeName, String packageName, boolean partialMatch, int acceptFlags, boolean checkRestrictions) {
if (USE_BINDING_SEARCH && this.searchFiles)
{
Answer answer =findBindingSearch(typeName, packageName, Binding.TYPE, partialMatch, acceptFlags, true, true, checkRestrictions, null,false,null);
if (answer!=null && answer.type==null && answer.element instanceof ITypeRoot)
{
ITypeRoot typeroot=(ITypeRoot)answer.element;
answer.type=typeroot.getType(typeName);
}
return answer;
}
return findType(typeName,
packageName,
partialMatch,
acceptFlags,
true/* consider secondary types */,
false/* do NOT wait for indexes */,
checkRestrictions,
null);
}
public Answer findBinding(String typeName, String packageName,int type, boolean partialMatch,
int acceptFlags, boolean checkRestrictions, boolean returnMultiple , String excludePath){
if ((type&Binding.COMPILATION_UNIT)!=0)
{
String fullName=typeName;
if (packageName.length()>0)
fullName=packageName+"."+typeName;
ITypeRoot compilationUnit = findCompilationUnit(fullName);
if (compilationUnit!=null )
{
return new Answer(compilationUnit, null);
}
type &= ~Binding.COMPILATION_UNIT;
if (type==0)
return null;
}
if ((type&Binding.PACKAGE)!=0)
{
type &= ~Binding.PACKAGE;
if (type==0)
return null;
}
if (USE_BINDING_SEARCH && searchFiles)
return findBindingSearch(typeName,
packageName,
type,
partialMatch,
acceptFlags,
true/* consider secondary types */,
false/* do NOT wait for indexes */,
checkRestrictions,
null, returnMultiple, excludePath);
return findBinding(typeName,
packageName,
type,
partialMatch,
acceptFlags,
true/* consider secondary types */,
false/* do NOT wait for indexes */,
checkRestrictions,
null);
}
/* return all CUs defining a type */
/**
* Returns all compilationUnits containing a specific type
*
* NOT FULLY IMPLEMENTED YET.
*
* @param typeName
* @param waitForIndexes
* @return all found compilationUnits containg [typeName]
*/
public IJavaScriptUnit[] findTypeSources(String typeName, boolean waitForIndexes) {
// Look for concerned package fragments
JavaElementRequestor elementRequestor = new JavaElementRequestor();
seekPackageFragments(IPackageFragment.DEFAULT_PACKAGE_NAME, false, elementRequestor);
IPackageFragment[] packages= elementRequestor.getPackageFragments();
IType type = null;
int length= packages.length;
HashSet projects = null;
IJavaScriptProject javaProject = null;
// Answer suggestedAnswer = null;
ArrayList found = new ArrayList();
for (int i= 0; i < length; i++) {
type = findType(typeName, packages[i], false, NameLookup.ACCEPT_ALL);
if (type != null && type.exists()) {
found.add(type);
}
if (javaProject == null) {
javaProject = packages[i].getJavaScriptProject();
} else if (projects == null) {
if (!javaProject.equals(packages[i].getJavaScriptProject())) {
projects = new HashSet(3);
projects.add(javaProject);
projects.add(packages[i].getJavaScriptProject());
}
} else {
projects.add(packages[i].getJavaScriptProject());
}
}
// If type was not found, try to find it as secondary in source folders
if (javaProject != null) {
if (projects == null) {
type = findSecondaryType(IPackageFragment.DEFAULT_PACKAGE_NAME, typeName, javaProject, waitForIndexes, new NullProgressMonitor());
} else {
Iterator allProjects = projects.iterator();
while (type == null && allProjects.hasNext()) {
type = findSecondaryType(IPackageFragment.DEFAULT_PACKAGE_NAME, typeName, (IJavaScriptProject) allProjects.next(), waitForIndexes, new NullProgressMonitor());
}
}
}
return null;
}
/**
* Find type. Considering secondary types and waiting for indexes depends on given corresponding parameters.
*/
public Answer findType(
String typeName,
String packageName,
boolean partialMatch,
int acceptFlags,
boolean considerSecondaryTypes,
boolean waitForIndexes,
boolean checkRestrictions,
IProgressMonitor monitor) {
if (packageName == null || packageName.length() == 0) {
packageName= IPackageFragment.DEFAULT_PACKAGE_NAME;
} else if (typeName.length() > 0 && ScannerHelper.isLowerCase(typeName.charAt(0))) {
// see if this is a known package and not a type
if (findPackageFragments(packageName + "." + typeName, false) != null) return null; //$NON-NLS-1$
}
// Look for concerned package fragments
JavaElementRequestor elementRequestor = new JavaElementRequestor();
seekPackageFragments(packageName, false, elementRequestor);
IPackageFragment[] packages= elementRequestor.getPackageFragments();
// Try to find type in package fragments list
IType type = null;
int length= packages.length;
HashSet projects = null;
IJavaScriptProject javaProject = null;
Answer suggestedAnswer = null;
for (int i= 0; i < length; i++) {
type = findType(typeName, packages[i], partialMatch, acceptFlags);
if (type != null) {
AccessRestriction accessRestriction = null;
if (checkRestrictions) {
accessRestriction = getViolatedRestriction(typeName, packageName, type, accessRestriction);
}
Answer answer = new Answer(type, accessRestriction);
if (!answer.ignoreIfBetter()) {
if (answer.isBetter(suggestedAnswer))
return answer;
} else if (answer.isBetter(suggestedAnswer))
// remember suggestion and keep looking
suggestedAnswer = answer;
}
else if (suggestedAnswer == null && considerSecondaryTypes) {
if (javaProject == null) {
javaProject = packages[i].getJavaScriptProject();
} else if (projects == null) {
if (!javaProject.equals(packages[i].getJavaScriptProject())) {
projects = new HashSet(3);
projects.add(javaProject);
projects.add(packages[i].getJavaScriptProject());
}
} else {
projects.add(packages[i].getJavaScriptProject());
}
}
}
if (suggestedAnswer != null)
// no better answer was found
return suggestedAnswer;
// If type was not found, try to find it as secondary in source folders
if (considerSecondaryTypes && javaProject != null) {
if (projects == null) {
type = findSecondaryType(packageName, typeName, javaProject, waitForIndexes, monitor);
} else {
Iterator allProjects = projects.iterator();
while (type == null && allProjects.hasNext()) {
type = findSecondaryType(packageName, typeName, (IJavaScriptProject) allProjects.next(), waitForIndexes, monitor);
}
}
}
return type == null ? null : new Answer(type, null);
}
public Answer findBinding(
String bindingName,
String packageName,
int bindingType,
boolean partialMatch,
int acceptFlags,
boolean considerSecondaryTypes,
boolean waitForIndexes,
boolean checkRestrictions,
IProgressMonitor monitor) {
if (packageName == null || packageName.length() == 0) {
packageName= IPackageFragment.DEFAULT_PACKAGE_NAME;
} else if (bindingName.length() > 0 && ScannerHelper.isLowerCase(bindingName.charAt(0))) {
// see if this is a known package and not a type
if (findPackageFragments(packageName + "." + bindingName, false) != null) return null; //$NON-NLS-1$
}
if (VERBOSE)
System.out.println("find binding: "+bindingName); //$NON-NLS-1$
// Look for concerned package fragments
JavaElementRequestor elementRequestor = new JavaElementRequestor();
seekPackageFragments(packageName, false, elementRequestor);
IPackageFragment[] packages= elementRequestor.getPackageFragments();
// Try to find type in package fragments list
// IType type = null;
Object element = null;
int length= packages.length;
HashSet projects = null;
IJavaScriptProject javaProject = null;
Answer suggestedAnswer = null;
for (int i= 0; i < length; i++) {
element = findBinding(bindingName, bindingType,packages[i], partialMatch, acceptFlags);
if (element != null) {
AccessRestriction accessRestriction = null;
if (checkRestrictions) {
accessRestriction = getViolatedRestriction(bindingName, packageName, element, accessRestriction);
}
char[] path = null;
if(element instanceof SourceTypeBinding) {
path = ((SourceTypeBinding)element).getFileName();
}else if ( element instanceof ReferenceBinding) {
path = ((ReferenceBinding)element).getFileName();
}else if(element instanceof SourceType){
path = ((SourceType)element).getPath().toString().toCharArray();
}
if(path!=null && !getRestrictedAccessRequestor().acceptBinding(bindingType, acceptFlags, packageName.toCharArray(), bindingName.toCharArray(), new String(path), accessRestriction)){
element = null;
continue;
}
//
Answer answer = new Answer(element, accessRestriction);
if (!answer.ignoreIfBetter()) {
if (answer.isBetter(suggestedAnswer))
return answer;
} else if (answer.isBetter(suggestedAnswer))
// remember suggestion and keep looking
suggestedAnswer = answer;
}
else if (suggestedAnswer == null && considerSecondaryTypes) {
if (javaProject == null) {
javaProject = packages[i].getJavaScriptProject();
} else if (projects == null) {
if (!javaProject.equals(packages[i].getJavaScriptProject())) {
projects = new HashSet(3);
projects.add(javaProject);
projects.add(packages[i].getJavaScriptProject());
}
} else {
projects.add(packages[i].getJavaScriptProject());
}
}
}
if (suggestedAnswer != null)
// no better answer was found
return suggestedAnswer;
// // If type was not found, try to find it as secondary in source folders
// if (considerSecondaryTypes && javaProject != null) {
// if (projects == null) {
// type = findSecondaryType(packageName, bindingName, javaProject, waitForIndexes, monitor);
// } else {
// Iterator allProjects = projects.iterator();
// while (type == null && allProjects.hasNext()) {
// type = findSecondaryType(packageName, typeName, (IJavaScriptProject) allProjects.next(), waitForIndexes, monitor);
// }
// }
// }
return element == null ? null : new Answer(element, null);
}
private AccessRestriction getViolatedRestriction(String typeName, String packageName, IType type, AccessRestriction accessRestriction) {
PackageFragmentRoot root = (PackageFragmentRoot) type.getAncestor(IJavaScriptElement.PACKAGE_FRAGMENT_ROOT);
ClasspathEntry entry = (ClasspathEntry) this.rootToResolvedEntries.get(root);
if (entry != null) { // reverse map always contains resolved CP entry
AccessRuleSet accessRuleSet = entry.getAccessRuleSet();
if (accessRuleSet != null) {
// TODO (philippe) improve char[] <-> String conversions to avoid performing them on the fly
char[][] packageChars = CharOperation.splitOn('.', packageName.toCharArray());
char[] typeChars = typeName.toCharArray();
accessRestriction = accessRuleSet.getViolatedRestriction(CharOperation.concatWith(packageChars, typeChars, '/'));
}
}
return accessRestriction;
}
private AccessRestriction getViolatedRestriction(String typeName, String packageName, Object element, AccessRestriction accessRestriction) {
//TODO: implement
// System.out.println("implement NameLookup.getViolatedRestriction");
// PackageFragmentRoot root = (PackageFragmentRoot) type.getAncestor(IJavaScriptElement.PACKAGE_FRAGMENT_ROOT);
// ClasspathEntry entry = (ClasspathEntry) this.rootToResolvedEntries.get(root);
// if (entry != null) { // reverse map always contains resolved CP entry
// AccessRuleSet accessRuleSet = entry.getAccessRuleSet();
// if (accessRuleSet != null) {
// // TODO (philippe) improve char[] <-> String conversions to avoid performing them on the fly
// char[][] packageChars = CharOperation.splitOn('.', packageName.toCharArray());
// char[] typeChars = typeName.toCharArray();
// accessRestriction = accessRuleSet.getViolatedRestriction(CharOperation.concatWith(packageChars, typeChars, '/'));
// }
// }
return accessRestriction;
}
/**
* Returns the first type in the given package whose name
* matches the given (unqualified) name, or <code>null</code> if none
* exist. Specifying a <code>null</code> package will result in no matches.
* The domain of the search is bounded by the Java project from which
* this name lookup was obtained.
*
* @param name the name of the type to find
* @param pkg the package to search
* @param partialMatch partial name matches qualify when <code>true</code>,
* only exact name matches qualify when <code>false</code>
* @param acceptFlags a bit mask describing if classes, interfaces or both classes and interfaces
* are desired results. If no flags are specified, all types are returned.
* @param considerSecondaryTypes flag to know whether secondary types has to be considered
* during the search
*
* @see #ACCEPT_CLASSES
* @see #ACCEPT_INTERFACES
* @see #ACCEPT_ENUMS
* @see #ACCEPT_ANNOTATIONS
*/
public IType findType(String name, IPackageFragment pkg, boolean partialMatch, int acceptFlags, boolean considerSecondaryTypes) {
IType type = findType(name, pkg, partialMatch, acceptFlags);
if (type == null && considerSecondaryTypes) {
type = findSecondaryType(pkg.getElementName(), name, pkg.getJavaScriptProject(), false, null);
}
return type;
}
/**
* Returns the first type in the given package whose name
* matches the given (unqualified) name, or <code>null</code> if none
* exist. Specifying a <code>null</code> package will result in no matches.
* The domain of the search is bounded by the Java project from which
* this name lookup was obtained.
* <br>
* Note that this method does not find secondary types.
* <br>
* @param name the name of the type to find
* @param pkg the package to search
* @param partialMatch partial name matches qualify when <code>true</code>,
* only exact name matches qualify when <code>false</code>
* @param acceptFlags a bit mask describing if classes, interfaces or both classes and interfaces
* are desired results. If no flags are specified, all types are returned.
*
* @see #ACCEPT_CLASSES
* @see #ACCEPT_INTERFACES
* @see #ACCEPT_ENUMS
* @see #ACCEPT_ANNOTATIONS
*/
public IType findType(String name, IPackageFragment pkg, boolean partialMatch, int acceptFlags) {
if (pkg == null) return null;
// Return first found (ignore duplicates).
SingleTypeRequestor typeRequestor = new SingleTypeRequestor();
seekTypes(name, pkg, partialMatch, acceptFlags, typeRequestor);
return typeRequestor.getType();
}
public IJavaScriptElement findBinding(String name, int type, IPackageFragment pkg, boolean partialMatch, int acceptFlags) {
if (pkg == null) return null;
// Return first found (ignore duplicates).
JavaElementRequestor requestor = new JavaElementRequestor();
seekBindings(name,type, pkg, partialMatch, acceptFlags, requestor);
IField[] fields = requestor.getFields();
IFunction[] methods = requestor.getMethods();
IType[] types = requestor.getTypes();
switch (type)
{
case Binding.FIELD | Binding.METHOD:
if (methods.length>0)
return methods[0];
case Binding.FIELD:
return (fields.length>0)?fields[0]:null;
case Binding.METHOD:
return (methods.length>0)?methods[0]:null;
case Binding.TYPE:
case Binding.TYPE|Binding.PACKAGE:
return (types.length>0)?types[0]:null;
default:
{
if ((Binding.TYPE & type)!=0)
{
if (types.length>0)
return types[0];
}
if ((Binding.METHOD & type)!=0)
{
if (methods.length>0)
return methods[0];
}
if ((Binding.VARIABLE & type)!=0)
{
if (fields.length>0)
return fields[0];
}
}
}
return null;
}
/**
* Returns the type specified by the qualified name, or <code>null</code>
* if none exist. The domain of
* the search is bounded by the Java project from which this name lookup was obtained.
*
* @param name the name of the type to find
* @param partialMatch partial name matches qualify when <code>true</code>,
* only exact name matches qualify when <code>false</code>
* @param acceptFlags a bit mask describing if classes, interfaces or both classes and interfaces
* are desired results. If no flags are specified, all types are returned.
*
* @see #ACCEPT_CLASSES
* @see #ACCEPT_INTERFACES
* @see #ACCEPT_ENUMS
* @see #ACCEPT_ANNOTATIONS
*/
public IType findType(String name, boolean partialMatch, int acceptFlags) {
NameLookup.Answer answer = findType(name, partialMatch, acceptFlags, false/*don't check restrictions*/);
return answer == null ? null : answer.type;
}
public Answer findType(String name, boolean partialMatch, int acceptFlags, boolean checkRestrictions) {
return findType(name, partialMatch, acceptFlags, true/*consider secondary types*/, true/*wait for indexes*/, checkRestrictions, null);
}
public Answer findType(String name, boolean partialMatch, int acceptFlags, boolean considerSecondaryTypes, boolean waitForIndexes, boolean checkRestrictions, IProgressMonitor monitor) {
// int index= name.lastIndexOf('.');
String className= null, packageName= null;
// if (index == -1) {
packageName= IPackageFragment.DEFAULT_PACKAGE_NAME;
className= name;
// } else {
// packageName= name.substring(0, index);
// className= name.substring(index + 1);
// }
if (USE_BINDING_SEARCH && searchFiles)
return findBindingSearch(className, packageName, Binding.TYPE, partialMatch, acceptFlags, considerSecondaryTypes, waitForIndexes, checkRestrictions, monitor,true,null);
return findType(className, packageName, partialMatch, acceptFlags, considerSecondaryTypes, waitForIndexes, checkRestrictions, monitor);
}
private IType getMemberType(IType type, String name, int dot) {
//while (dot != -1) {
//int start = dot+1;
// dot = name.indexOf('.', start);
// String typeName = name.substring(start, dot == -1 ? name.length() : dot);
// type = type.getType(name);
//}
return type;
}
public boolean isPackage(String[] pkgName) {
return this.packageFragments.get(pkgName) != null;
}
/**
* Returns true if the given element's name matches the
* specified <code>searchName</code>, otherwise false.
*
* <p>The <code>partialMatch</code> argument indicates partial matches
* should be considered.
* NOTE: in partialMatch mode, the case will be ignored, and the searchName must already have
* been lowercased.
*/
protected boolean nameMatches(String searchName, IJavaScriptElement element, boolean partialMatch) {
if (partialMatch) {
// partial matches are used in completion mode, thus case insensitive mode
return element.getElementName().toLowerCase().startsWith(searchName);
} else {
return element.getElementName().equals(searchName);
}
}
/**
* Returns true if the given cu's name matches the
* specified <code>searchName</code>, otherwise false.
*
* <p>The <code>partialMatch</code> argument indicates partial matches
* should be considered.
* NOTE: in partialMatch mode, the case will be ignored, and the searchName must already have
* been lowercased.
*/
protected boolean nameMatches(String searchName, IJavaScriptUnit cu, boolean partialMatch) {
if (partialMatch) {
// partial matches are used in completion mode, thus case insensitive mode
return cu.getElementName().toLowerCase().startsWith(searchName);
} else {
return Util.equalsIgnoreJavaLikeExtension(cu.getElementName(), searchName);
}
}
/**
* Notifies the given requestor of all package fragments with the
* given name. Checks the requestor at regular intervals to see if the
* requestor has canceled. The domain of
* the search is bounded by the <code>IJavaScriptProject</code>
* this <code>NameLookup</code> was obtained from.
*
* @param partialMatch partial name matches qualify when <code>true</code>;
* only exact name matches qualify when <code>false</code>
*/
public void seekPackageFragments(String name, boolean partialMatch, IJavaElementRequestor requestor) {
/* if (VERBOSE) {
Util.verbose(" SEEKING PACKAGE FRAGMENTS"); //$NON-NLS-1$
Util.verbose(" -> name: " + name); //$NON-NLS-1$
Util.verbose(" -> partial match:" + partialMatch); //$NON-NLS-1$
}
*/
for (int i = 0; i < this.packageFragmentRoots.length; i++) {
IJavaScriptElement[] children;
try {
if (this.searchFiles || packageFragmentRoots[i].isLibrary())
{
children = packageFragmentRoots[i].getChildren();
for (int j = 0; j < children.length; j++) {
requestor.acceptPackageFragment((IPackageFragment)children[j]);
}
}
} catch (JavaScriptModelException e) {}
}
// if (partialMatch) {
// String[] splittedName = splitPackageName(name);
// Object[][] keys = this.packageFragments.keyTable;
// for (int i = 0, length = keys.length; i < length; i++) {
// if (requestor.isCanceled())
// return;
// String[] pkgName = (String[]) keys[i];
// if (pkgName != null && Util.startsWithIgnoreCase(pkgName, splittedName)) {
// Object value = this.packageFragments.valueTable[i];
// if (value instanceof PackageFragmentRoot) {
// PackageFragmentRoot root = (PackageFragmentRoot) value;
// requestor.acceptPackageFragment(root.getPackageFragment(pkgName));
// } else {
// IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) value;
// for (int j = 0, length2 = roots.length; j < length2; j++) {
// if (requestor.isCanceled())
// return;
// PackageFragmentRoot root = (PackageFragmentRoot) roots[j];
// requestor.acceptPackageFragment(root.getPackageFragment(pkgName));
// }
// }
// }
// }
// } else {
// String[] splittedName = splitPackageName(name);
// Object value = this.packageFragments.get(splittedName);
// if (value instanceof PackageFragmentRoot) {
// requestor.acceptPackageFragment(((PackageFragmentRoot) value).getPackageFragment(splittedName));
// } else {
// IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) value;
// if (roots != null) {
// for (int i = 0, length = roots.length; i < length; i++) {
// if (requestor.isCanceled())
// return;
// PackageFragmentRoot root = (PackageFragmentRoot) roots[i];
// requestor.acceptPackageFragment(root.getPackageFragment(splittedName));
// }
// }
// }
// }
// if (name==null || name.equals(IPackageFragment.DEFAULT_PACKAGE_NAME))
// {
// for (int i = 0; i < this.packageFragmentRoots.length; i++) {
// if (packageFragmentRoots[i] instanceof LibraryFragmentRoot)
// {
// IJavaScriptElement[] children;
// try {
// children = packageFragmentRoots[i].getChildren();
// for (int j = 0; j < children.length; j++) {
// requestor.acceptPackageFragment((IPackageFragment)children[j]);
// }
// } catch (JavaScriptModelException e) {
// }
// }
// }
// }
}
// private String [] splitPackageName(String name)
// {
// String[] strings;
// int index=Util.indexOfJavaLikeExtension(name);
// if (index>=0)
// {
// String extension=name.substring(index+1);
// name=name.substring(0,index);
// strings= Util.splitOn('.', name, 0, name.length());
// strings[strings.length-1]=strings[strings.length-1]+extension;
// }
// else
// strings = Util.splitOn('.', name, 0, name.length());
//
// return strings;
// }
/**
* Notifies the given requestor of all types (classes and interfaces) in the
* given package fragment with the given (unqualified) name.
* Checks the requestor at regular intervals to see if the requestor
* has canceled. If the given package fragment is <code>null</code>, all types in the
* project whose simple name matches the given name are found.
*
* @param name The name to search
* @param pkg The corresponding package fragment
* @param partialMatch partial name matches qualify when <code>true</code>;
* only exact name matches qualify when <code>false</code>
* @param acceptFlags a bit mask describing if classes, interfaces or both classes and interfaces
* are desired results. If no flags are specified, all types are returned.
* @param requestor The requestor that collects the result
*
* @see #ACCEPT_CLASSES
* @see #ACCEPT_INTERFACES
* @see #ACCEPT_ENUMS
* @see #ACCEPT_ANNOTATIONS
*/
public void seekTypes(String name, IPackageFragment pkg, boolean partialMatch, int acceptFlags, IJavaElementRequestor requestor) {
/* if (VERBOSE) {
Util.verbose(" SEEKING TYPES"); //$NON-NLS-1$
Util.verbose(" -> name: " + name); //$NON-NLS-1$
Util.verbose(" -> pkg: " + ((JavaElement) pkg).toStringWithAncestors()); //$NON-NLS-1$
Util.verbose(" -> partial match:" + partialMatch); //$NON-NLS-1$
}
*/
String matchName= partialMatch ? name.toLowerCase() : name;
if (pkg == null) {
findAllTypes(matchName, partialMatch, acceptFlags, requestor);
return;
}
IPackageFragmentRoot root= (IPackageFragmentRoot) pkg.getParent();
try {
// look in working copies first
int firstDot = -1;
String topLevelTypeName = matchName;
int packageFlavor= root.getKind();
// if (this.typesInWorkingCopies != null || packageFlavor == IPackageFragmentRoot.K_SOURCE) {
// firstDot = matchName.indexOf('.');
// if (!partialMatch)
// topLevelTypeName = firstDot == -1 ? matchName : matchName.substring(0, firstDot);
// }
if (this.typesInWorkingCopies != null) {
if (seekTypesInWorkingCopies(matchName, pkg, firstDot, partialMatch, topLevelTypeName, acceptFlags, requestor))
return;
}
// look in model
switch (packageFlavor) {
case IPackageFragmentRoot.K_BINARY :
matchName= matchName.replace('.', '$');
seekBindingsInBinaryPackage(matchName,Binding.TYPE, pkg, partialMatch, acceptFlags, requestor);
break;
case IPackageFragmentRoot.K_SOURCE :
seekTypesInSourcePackage(matchName, pkg, firstDot, partialMatch, topLevelTypeName, acceptFlags, requestor);
break;
default :
return;
}
} catch (JavaScriptModelException e) {
return;
}
}
public void seekBindings(String name, int bindingType, IPackageFragment pkg, boolean partialMatch, int acceptFlags, IJavaElementRequestor requestor) {
/* if (VERBOSE) {
Util.verbose(" SEEKING TYPES"); //$NON-NLS-1$
Util.verbose(" -> name: " + name); //$NON-NLS-1$
Util.verbose(" -> pkg: " + ((JavaElement) pkg).toStringWithAncestors()); //$NON-NLS-1$
Util.verbose(" -> partial match:" + partialMatch); //$NON-NLS-1$
}
*/
String matchName= partialMatch ? name.toLowerCase() : name;
if (pkg == null) {
findAllBindings(matchName, bindingType, partialMatch, acceptFlags, requestor);
return;
}
IPackageFragmentRoot root= (IPackageFragmentRoot) pkg.getParent();
try {
// look in working copies first
int firstDot = -1;
String topLevelTypeName = null;
int packageFlavor= root.getKind();
if (this.typesInWorkingCopies != null || packageFlavor == IPackageFragmentRoot.K_SOURCE) {
firstDot = matchName.indexOf('.');
if (!partialMatch)
topLevelTypeName = firstDot == -1 ? matchName : matchName.substring(0, firstDot);
}
if (this.bindingsInWorkingCopies != null) {
if (seekBindingsInWorkingCopies(matchName,bindingType, firstDot, partialMatch, topLevelTypeName, acceptFlags, requestor))
return;
}
// look in model
switch (packageFlavor) {
case IPackageFragmentRoot.K_BINARY :
// matchName= matchName.replace('.', '$');
seekBindingsInBinaryPackage(matchName, bindingType,pkg, partialMatch, acceptFlags, requestor);
break;
case IPackageFragmentRoot.K_SOURCE :
seekBindingsInSourcePackage(matchName, bindingType,pkg, firstDot, partialMatch, topLevelTypeName, acceptFlags, requestor);
break;
default :
return;
}
} catch (JavaScriptModelException e) {
return;
}
}
/**
* Performs type search in a binary package.
*/
// protected void seekTypesInBinaryPackage(String name, IPackageFragment pkg, boolean partialMatch, int acceptFlags, IJavaElementRequestor requestor) {
// long start = -1;
// if (VERBOSE)
// start = System.currentTimeMillis();
// try {
// if (!partialMatch) {
// // exact match
// if (requestor.isCanceled()) return;
// ClassFile classFile = new ClassFile((PackageFragment) pkg, name);
// if (classFile.existsUsingJarTypeCache()) {
// IType type = classFile.getType();
// if (acceptType(type, acceptFlags, false/*not a source type*/)) {
// requestor.acceptType(type);
// }
// }
// } else {
// IJavaScriptElement[] classFiles= null;
// try {
// classFiles= pkg.getChildren();
// } catch (JavaScriptModelException npe) {
// return; // the package is not present
// }
// int length= classFiles.length;
// String unqualifiedName = name;
// int index = name.lastIndexOf('$');
// if (index != -1) {
// //the type name of the inner type
// unqualifiedName = Util.localTypeName(name, index, name.length());
// // unqualifiedName is empty if the name ends with a '$' sign.
// // See http://dev.eclipse.org/bugs/show_bug.cgi?id=14642
// }
// int matchLength = name.length();
// for (int i = 0; i < length; i++) {
// if (requestor.isCanceled())
// return;
// IJavaScriptElement classFile= classFiles[i];
// // MatchName will never have the extension ".class" and the elementName always will.
// String elementName = classFile.getElementName();
// if (elementName.regionMatches(true /*ignore case*/, 0, name, 0, matchLength)) {
// IType type = ((ClassFile) classFile).getType();
// String typeName = type.getElementName();
// if (typeName.length() > 0 && !Character.isDigit(typeName.charAt(0))) { //not an anonymous type
// if (nameMatches(unqualifiedName, type, true/*partial match*/) && acceptType(type, acceptFlags, false/*not a source type*/))
// requestor.acceptType(type);
// }
// }
// }
// }
// } finally {
// if (VERBOSE)
// this.timeSpentInSeekTypesInBinaryPackage += System.currentTimeMillis()-start;
// }
// }
//
protected void seekBindingsInBinaryPackage(String name, int bindingType,IPackageFragment pkg, boolean partialMatch, int acceptFlags, IJavaElementRequestor requestor) {
long start = -1;
if (VERBOSE)
start = System.currentTimeMillis();
try {
this.acceptedCUs.clear();
IJavaScriptElement[] classFiles= null;
try {
classFiles= pkg.getChildren();
} catch (JavaScriptModelException npe) {
return; // the package is not present
}
int length= classFiles.length;
if (!partialMatch) {
for (int i = 0; i < length; i++) {
ClassFile classFile=(ClassFile)classFiles[i];
if (this.acceptedCUs.contains(classFile))
continue;
switch (bindingType) {
case Binding.TYPE:
case Binding.TYPE | Binding.PACKAGE:
IType type = classFile.getType(name);
if (acceptType(type, acceptFlags, false/*not a source type*/)) {
acceptedCUs.add(classFile);
requestor.acceptType(type);
}
break;
case Binding.VARIABLE:
// String cuName = cu.getElementName();
// int lastDot = cuName.lastIndexOf('.');
// if (lastDot != topLevelTypeName.length() || !topLevelTypeName.regionMatches(0, cuName, 0, lastDot))
// continue;
IField field = classFile.getField(name);
if (field.exists()) {
acceptedCUs.add(classFile);
requestor.acceptField(field);
}
break;
case Binding.METHOD:
// String cuName = cu.getElementName();
// int lastDot = cuName.lastIndexOf('.');
// if (lastDot != topLevelTypeName.length() || !topLevelTypeName.regionMatches(0, cuName, 0, lastDot))
// continue;
IFunction method = classFile.getFunction(name, null);
if (method.exists()) {
acceptedCUs.add(classFile);
requestor.acceptMethod(method);
}
break;
case Binding.METHOD | Binding.VARIABLE:
method = classFile.getFunction(name, null);
if (method!=null
&& method.exists()) {
acceptedCUs.add(classFile);
requestor.acceptMethod(method);
} else
{
field = classFile.getField(name);
if (field!=null && field.exists())
{
acceptedCUs.add(classFile);
requestor.acceptField(field);
}
}
break;
default:
{
if ((Binding.TYPE & bindingType)!=0)
{
IType thisType = classFile.getType(name);
if (acceptType(thisType, acceptFlags, false/*not a source type*/)) {
acceptedCUs.add(classFile);
requestor.acceptType(thisType);
}
}
if ((Binding.METHOD & bindingType)!=0)
{
method = classFile.getFunction(name, null);
if (method!=null && method.exists()) {
acceptedCUs.add(classFile);
requestor.acceptMethod(method);
}
}
if ((Binding.VARIABLE & bindingType)!=0)
{
field = classFile.getField(name);
if (field!=null && field.exists()) {
acceptedCUs.add(classFile);
requestor.acceptField(field);
}
}
}
}
}
} else {
String unqualifiedName = name;
int index = name.lastIndexOf('$');
if (index != -1) {
//the type name of the inner type
unqualifiedName = Util.localTypeName(name, index, name.length());
// unqualifiedName is empty if the name ends with a '$' sign.
// See http://dev.eclipse.org/bugs/show_bug.cgi?id=14642
}
int matchLength = name.length();
for (int i = 0; i < length; i++) {
if (requestor.isCanceled())
return;
IJavaScriptElement classFile= classFiles[i];
// MatchName will never have the extension ".class" and the elementName always will.
String elementName = classFile.getElementName();
if (elementName.regionMatches(true /*ignore case*/, 0, name, 0, matchLength)) {
IType type = ((ClassFile) classFile).getType();
String typeName = type.getElementName();
if (typeName.length() > 0 && !Character.isDigit(typeName.charAt(0))) { //not an anonymous type
if (nameMatches(unqualifiedName, type, true/*partial match*/) && acceptType(type, acceptFlags, false/*not a source type*/))
requestor.acceptType(type);
}
}
}
}
} finally {
if (VERBOSE)
this.timeSpentInSeekTypesInBinaryPackage += System.currentTimeMillis()-start;
}
}
/**
* Performs type search in a source package.
*/
protected void seekTypesInSourcePackage(
String name,
IPackageFragment pkg,
int firstDot,
boolean partialMatch,
String topLevelTypeName,
int acceptFlags,
IJavaElementRequestor requestor) {
long start = -1;
if (VERBOSE)
start = System.currentTimeMillis();
try {
if (!partialMatch) {
try {
IJavaScriptElement[] compilationUnits = pkg.getChildren();
for (int i = 0, length = compilationUnits.length; i < length; i++) {
if (requestor.isCanceled())
return;
IJavaScriptElement cu = compilationUnits[i];
// String cuName = cu.getElementName();
//int lastDot = cuName.lastIndexOf('.');
//if (lastDot != topLevelTypeName.length() || !topLevelTypeName.regionMatches(0, cuName, 0, lastDot)) \
//if(topLevelTypeName!=null && !topLevelTypeName.equals(cuName))
// continue;
IType type = ((IJavaScriptUnit) cu).getType(name);
//type = getMemberType(type, name, firstDot);
if (acceptType(type, acceptFlags, true/*a source type*/)) { // accept type checks for existence
requestor.acceptType(type);
break; // since an exact match was requested, no other matching type can exist
}
}
} catch (JavaScriptModelException e) {
// package doesn't exist -> ignore
}
} else {
try {
String cuPrefix = firstDot == -1 ? name : name.substring(0, firstDot);
IJavaScriptElement[] compilationUnits = pkg.getChildren();
for (int i = 0, length = compilationUnits.length; i < length; i++) {
if (requestor.isCanceled())
return;
IJavaScriptElement cu = compilationUnits[i];
if (!cu.getElementName().toLowerCase().startsWith(cuPrefix))
continue;
try {
IType[] types = ((IJavaScriptUnit) cu).getTypes();
for (int j = 0, typeLength = types.length; j < typeLength; j++)
seekTypesInTopLevelType(name, firstDot, types[j], requestor, acceptFlags);
} catch (JavaScriptModelException e) {
// cu doesn't exist -> ignore
}
}
} catch (JavaScriptModelException e) {
// package doesn't exist -> ignore
}
}
} finally {
if (VERBOSE)
this.timeSpentInSeekTypesInSourcePackage += System.currentTimeMillis()-start;
}
}
protected void seekBindingsInSourcePackage(
String name,
int bindingType,
IPackageFragment pkg,
int firstDot,
boolean partialMatch,
String topLevelTypeName,
int acceptFlags,
IJavaElementRequestor requestor) {
long start = -1;
if (VERBOSE)
start = System.currentTimeMillis();
try {
if (!partialMatch) {
try {
IJavaScriptElement[] compilationUnits = pkg.getChildren();
for (int i = 0, length = compilationUnits.length; i < length; i++) {
if (requestor.isCanceled())
return;
IJavaScriptElement cu = compilationUnits[i];
if (cu instanceof IJavaScriptUnit && ((IJavaScriptUnit)cu).isWorkingCopy())
continue;
if (this.acceptedCUs.contains(cu))
continue;
switch (bindingType) {
case Binding.TYPE:
// String cuName = cu.getElementName();
// int lastDot = cuName.lastIndexOf('.');
// if (lastDot != topLevelTypeName.length() || !topLevelTypeName.regionMatches(0, cuName, 0, lastDot))
// continue;
IType type = ((IJavaScriptUnit) cu).getType(topLevelTypeName);
type = getMemberType(type, name, firstDot);
if (acceptType(type, acceptFlags, true/*a source type*/)) { // accept type checks for existence
acceptedCUs.add(cu);
requestor.acceptType(type);
break; // since an exact match was requested, no other matching type can exist
}
break;
case Binding.VARIABLE:
// String cuName = cu.getElementName();
// int lastDot = cuName.lastIndexOf('.');
// if (lastDot != topLevelTypeName.length() || !topLevelTypeName.regionMatches(0, cuName, 0, lastDot))
// continue;
IField field = ((IJavaScriptUnit) cu).getField(name);
if (field.exists()) {
acceptedCUs.add(cu);
requestor.acceptField(field);
}
break;
case Binding.METHOD:
// String cuName = cu.getElementName();
// int lastDot = cuName.lastIndexOf('.');
// if (lastDot != topLevelTypeName.length() || !topLevelTypeName.regionMatches(0, cuName, 0, lastDot))
// continue;
IFunction method = ((IJavaScriptUnit) cu).getFunction(name, null);
if (method.exists()) {
acceptedCUs.add(cu);
requestor.acceptMethod(method);
}
break;
case Binding.METHOD | Binding.VARIABLE:
method = ((IJavaScriptUnit) cu).getFunction(name, null);
if (method!=null)
if (method.exists()) {
acceptedCUs.add(cu);
requestor.acceptMethod(method);
} else
{
field = ((IJavaScriptUnit) cu).getField(name);
if (field.exists()) {
acceptedCUs.add(cu);
requestor.acceptField(field);
}
}
break;
default:
break;
}
}
} catch (JavaScriptModelException e) {
// package doesn't exist -> ignore
}
} else {
try {
String cuPrefix = firstDot == -1 ? name : name.substring(0, firstDot);
IJavaScriptElement[] compilationUnits = pkg.getChildren();
for (int i = 0, length = compilationUnits.length; i < length; i++) {
if (requestor.isCanceled())
return;
IJavaScriptElement cu = compilationUnits[i];
if (!cu.getElementName().toLowerCase().startsWith(cuPrefix))
continue;
try {
IType[] types = ((IJavaScriptUnit) cu).getTypes();
for (int j = 0, typeLength = types.length; j < typeLength; j++)
seekTypesInTopLevelType(name, firstDot, types[j], requestor, acceptFlags);
} catch (JavaScriptModelException e) {
// cu doesn't exist -> ignore
}
}
} catch (JavaScriptModelException e) {
// package doesn't exist -> ignore
}
}
} finally {
if (VERBOSE)
this.timeSpentInSeekTypesInSourcePackage += System.currentTimeMillis()-start;
}
}
/**
* Notifies the given requestor of all types (classes and interfaces) in the
* given type with the given (possibly qualified) name. Checks
* the requestor at regular intervals to see if the requestor
* has canceled.
*/
protected boolean seekTypesInType(String prefix, int firstDot, IType type, IJavaElementRequestor requestor, int acceptFlags) {
IType[] types= null;
try {
types= type.getTypes();
} catch (JavaScriptModelException npe) {
return false; // the enclosing type is not present
}
int length= types.length;
if (length == 0) return false;
String memberPrefix = prefix;
boolean isMemberTypePrefix = false;
if (firstDot != -1) {
memberPrefix= prefix.substring(0, firstDot);
isMemberTypePrefix = true;
}
for (int i= 0; i < length; i++) {
if (requestor.isCanceled())
return false;
IType memberType= types[i];
if (memberType.getElementName().toLowerCase().startsWith(memberPrefix))
if (isMemberTypePrefix) {
String subPrefix = prefix.substring(firstDot + 1, prefix.length());
return seekTypesInType(subPrefix, subPrefix.indexOf('.'), memberType, requestor, acceptFlags);
} else {
if (acceptType(memberType, acceptFlags, true/*a source type*/)) {
requestor.acceptMemberType(memberType);
return true;
}
}
}
return false;
}
protected boolean seekTypesInTopLevelType(String prefix, int firstDot, IType topLevelType, IJavaElementRequestor requestor, int acceptFlags) {
if (!topLevelType.getElementName().toLowerCase().startsWith(prefix))
return false;
if (firstDot == -1) {
if (acceptType(topLevelType, acceptFlags, true/*a source type*/)) {
requestor.acceptType(topLevelType);
return true;
}
} else {
return seekTypesInType(prefix, firstDot, topLevelType, requestor, acceptFlags);
}
return false;
}
/*
* Seeks the type with the given name in the map of types with precedence (coming from working copies)
* Return whether a type has been found.
*/
protected boolean seekTypesInWorkingCopies(
String name,
IPackageFragment pkg,
int firstDot,
boolean partialMatch,
String topLevelTypeName,
int acceptFlags,
IJavaElementRequestor requestor) {
if (!partialMatch) {
HashMap typeMap = (HashMap) (this.typesInWorkingCopies == null ? null : this.typesInWorkingCopies.get(pkg));
if (typeMap != null) {
Object object = typeMap.get(topLevelTypeName);
if (object instanceof IType) {
IType type = getMemberType((IType) object, name, firstDot);
if (acceptType(type, acceptFlags, true/*a source type*/)) {
requestor.acceptType(type);
return true; // don't continue with compilation unit
}
} else if (object instanceof IType[]) {
if (object == NO_TYPES) return true; // all types where deleted -> type is hidden
IType[] topLevelTypes = (IType[]) object;
for (int i = 0, length = topLevelTypes.length; i < length; i++) {
if (requestor.isCanceled())
return false;
IType type = getMemberType(topLevelTypes[i], name, firstDot);
if (acceptType(type, acceptFlags, true/*a source type*/)) {
requestor.acceptType(type);
return true; // return the first one
}
}
}
}
} else {
HashMap typeMap = (HashMap) (this.typesInWorkingCopies == null ? null : this.typesInWorkingCopies.get(pkg));
if (typeMap != null) {
Iterator iterator = typeMap.values().iterator();
while (iterator.hasNext()) {
if (requestor.isCanceled())
return false;
Object object = iterator.next();
if (object instanceof IType) {
seekTypesInTopLevelType(name, firstDot, (IType) object, requestor, acceptFlags);
} else if (object instanceof IType[]) {
IType[] topLevelTypes = (IType[]) object;
for (int i = 0, length = topLevelTypes.length; i < length; i++)
seekTypesInTopLevelType(name, firstDot, topLevelTypes[i], requestor, acceptFlags);
}
}
}
}
return false;
}
private boolean checkBindingAccept(String topLevelTypeName,HashMap []bindingsMap,int bindingType,IJavaElementRequestor requestor)
{
Object object = bindingsMap[bindingType].get(topLevelTypeName);
if (object instanceof IJavaScriptElement) {
if (doAcceptBinding((IJavaScriptElement)object, bindingType , true/*a source type*/,requestor)) {
return true; // don't continue with compilation unit
}
} else if (object instanceof IJavaScriptElement[]) {
if (object == NO_BINDINGS) return true; // all types where deleted -> type is hidden
IJavaScriptElement[] topLevelElements = (IJavaScriptElement[]) object;
boolean isAnyBindingAccepted = false;
for (int i = 0, length = topLevelElements.length; i < length; i++) {
if (requestor.isCanceled())
return false;
if (doAcceptBinding(topLevelElements[i], bindingType, true/*a source type*/,requestor)) {
isAnyBindingAccepted = true;
}
}
return isAnyBindingAccepted;
}
return false;
}
protected boolean seekBindingsInWorkingCopies(
String name,
int bindingType,
int firstDot,
boolean partialMatch,
String topLevelTypeName,
int acceptFlags,
IJavaElementRequestor requestor) {
bindingType=bindingType & Binding.BASIC_BINDINGS_MASK;
if (!partialMatch) {
HashMap []bindingsMap = (this.bindingsInWorkingCopies == null ? null : this.bindingsInWorkingCopies);
if (bindingsMap != null) {
if (checkBindingAccept(topLevelTypeName, bindingsMap, bindingType, requestor))
return true;
if ((bindingType&Binding.VARIABLE)>0 && bindingType!=Binding.VARIABLE)
if (checkBindingAccept(topLevelTypeName, bindingsMap, Binding.VARIABLE, requestor))
return true;
if ((bindingType&Binding.LOCAL)>0 && bindingType!=Binding.LOCAL)
if (checkBindingAccept(topLevelTypeName, bindingsMap, Binding.LOCAL, requestor))
return true;
if ((bindingType&Binding.METHOD)>0 && bindingType!=Binding.METHOD)
if (checkBindingAccept(topLevelTypeName, bindingsMap, Binding.METHOD, requestor))
return true;
if ((bindingType&Binding.TYPE)>0 && bindingType!=Binding.TYPE)
if (checkBindingAccept(topLevelTypeName, bindingsMap, Binding.TYPE, requestor))
return true;
}
} else {
HashMap[] bindingsMap = (this.bindingsInWorkingCopies == null ? null : this.bindingsInWorkingCopies);
if (bindingsMap != null) {
Iterator iterator = bindingsMap[bindingType].values().iterator();
while (iterator.hasNext()) {
if (requestor.isCanceled())
return false;
Object object = iterator.next();
if (object instanceof IType) {
seekTypesInTopLevelType(name, firstDot, (IType) object, requestor, acceptFlags);
} else if (object instanceof IType[]) {
IType[] topLevelTypes = (IType[]) object;
for (int i = 0, length = topLevelTypes.length; i < length; i++)
seekTypesInTopLevelType(name, firstDot, topLevelTypes[i], requestor, acceptFlags);
}
}
}
}
return false;
}
public static final boolean USE_BINDING_SEARCH=true;
private HandleFactory handleFactory;
protected IJavaScriptSearchScope searchScope;
public Answer findBindingSearch(
String bindingName,
String packageName,
int bindingType,
boolean partialMatch,
int acceptFlags,
boolean considerSecondaryTypes,
boolean waitForIndexes,
boolean checkRestrictions,
IProgressMonitor progressMonitor, boolean returnMultiple, String exclude) {
class MyRequestor implements IJavaElementRequestor
{
ArrayList element;
public void acceptField(IField field) {
if(element == null)
element = new ArrayList();
element.add(field);
}
public void acceptInitializer(IInitializer initializer) {
}
public void acceptMemberType(IType type) {
if(element == null)
element = new ArrayList();
element.add(type);
}
public void acceptMethod(IFunction method) {
if(element == null)
element = new ArrayList();
element.add(method);
}
public void acceptPackageFragment(
IPackageFragment packageFragment) {
}
public void acceptType(IType type) {
if(element == null)
element = new ArrayList();
element.add(type);
}
public boolean isCanceled() {
return false;
}
}
if (this.searchScope==null)
this.searchScope = BasicSearchEngine.createJavaSearchScope(packageFragmentRoots);
ArrayList foundAnswers=new ArrayList();
Path excludePath= (exclude!=null)? new Path(exclude) : null;
MyRequestor requestor=new MyRequestor();
seekBindingsInWorkingCopies(bindingName, bindingType, -1, partialMatch,
bindingName, acceptFlags, requestor);
if (requestor.element != null) {
for(int i = 0; i < requestor.element.size(); i++) {
IOpenable openable = ((IJavaScriptElement)requestor.element.get(i)).getOpenable();
if (excludePath!=null && ((IJavaScriptElement)requestor.element.get(i)).getPath().equals(excludePath))
continue;
if (!returnMultiple) {
return new Answer(openable, null);
} else
foundAnswers.add(openable);
}
requestor.element=null;
}
/*
* if (true){ findTypes(new String(prefix), storage,
* NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES); return; }
*/
try {
IRestrictedAccessBindingRequestor bindingAcceptor = getRestrictedAccessRequestor();
if (exclude!=null)
exclude=exclude.replace('\\', '/');
bindingAcceptor.setExcludePath(exclude);
try {
int matchRule = SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE;
new BasicSearchEngine().searchAllBindingNames(
CharOperation.NO_CHAR,
bindingName.toCharArray(),
bindingType,
matchRule, // not case sensitive
/*IJavaScriptSearchConstants.TYPE,*/ this.searchScope,
bindingAcceptor, IJavaScriptSearchConstants.WAIT_UNTIL_READY_TO_SEARCH,
false,
progressMonitor);
if (bindingAcceptor.getFoundPath()!=null)
{
Object[] foundPaths = bindingAcceptor.getFoundPaths().toArray();
for (int i = 0; i < foundPaths.length; ++i) {
String path = (String) foundPaths[i];
IOpenable openable ; //= createOpenable(getRestrictedAccessRequestor().getFoundPath(), this.searchScope);
// if (openable!=null)
// return new Answer(openable, null);
if (this.handleFactory == null)
this.handleFactory = new HandleFactory();
openable = this.handleFactory.createOpenable(path, this.searchScope);
if (openable!=null)
{
if (!returnMultiple)
return new Answer(openable, null);
else
foundAnswers.add(openable);
}
}
if (foundAnswers.size()>0 && returnMultiple)
return new Answer(foundAnswers.toArray(),null);
}
} catch (OperationCanceledException e) {
return findBinding( bindingName,packageName,bindingType,partialMatch,acceptFlags,considerSecondaryTypes,waitForIndexes,
checkRestrictions,progressMonitor);
}
finally
{
bindingAcceptor.reset();
}
} catch (JavaScriptModelException e) {
return findBinding( bindingName,packageName,bindingType,partialMatch,acceptFlags,considerSecondaryTypes,waitForIndexes,
checkRestrictions,progressMonitor);
}
if (foundAnswers.size()>0 && returnMultiple)
return new Answer(foundAnswers.toArray(),null);
return null;
}
/* creates an openable from PackageFragmentRoots in this lookup
* i thought i was going to use, but found another way. This may still
* be faster then the current method so leaveing in case...
*
* */
public IOpenable createOpenable(String resourcePath, IJavaScriptSearchScope scope) {
if(packageFragmentRoots==null) return null;
IPath resourceP = new Path(resourcePath);
for(int i = 0;i<packageFragmentRoots.length;i++) {
IPackageFragmentRoot root = packageFragmentRoots[i];
IPath fragPath = root.getPath();
String fileName = resourceP.lastSegment();
IPath rootPostFix=null;
if( root.isLanguageRuntime() /*&& restrictToLanguage*/) {
int rootSegs = fragPath.segmentCount();
int resourceSegs = resourceP.segmentCount();
if(rootSegs>resourceSegs)
rootPostFix = (fragPath.removeFirstSegments(rootSegs - resourceSegs )).setDevice(null).makeAbsolute();
}
if(fragPath.isPrefixOf(resourceP) || (rootPostFix!=null && rootPostFix.equals(resourceP.makeAbsolute()))) {
if(root instanceof LibraryFragmentRoot /*&& (!restrictToLanguage || root.isLanguageRuntime() )*/ ) {
IClassFile file = root.getPackageFragment(root.getPath().toString()).getClassFile(root.getPath().toString());
return file;
}else{
if(resourceP.toFile().exists()){
IClassFile file = root.getPackageFragment(resourcePath).getClassFile(resourcePath);
return file;
}else {
String pkgName = resourcePath.substring(fragPath.toString().length());
int indexName = pkgName.indexOf(fileName);
if(indexName>-1) {
pkgName = pkgName.substring(0,indexName-1);
}
IJavaScriptUnit file = root.getPackageFragment(pkgName).getJavaScriptUnit((fileName));
return file;
}
}
}
}
return null;
}
public void setScriptFile(IInferenceFile compUnit)
{
InferrenceProvider[] inferenceProviders = InferrenceManager.getInstance().getInferenceProviders(compUnit);
if (inferenceProviders!=null && inferenceProviders.length>0)
{
for(int i = 0; i < inferenceProviders.length; i++) {
ResolutionConfiguration resolutionConfiguration = inferenceProviders[i].getResolutionConfiguration();
if (resolutionConfiguration!=null)
searchFiles=resolutionConfiguration.searchAllFiles();
if(!searchFiles)
break;
}
}
}
}