package org.eclipse.jdt.internal.core; | |
/* | |
* (c) Copyright IBM Corp. 2000, 2001. | |
* All Rights Reserved. | |
*/ | |
import org.eclipse.core.runtime.*; | |
import org.eclipse.core.resources.*; | |
import org.eclipse.jdt.core.search.*; | |
import org.eclipse.jdt.internal.compiler.env.*; | |
import org.eclipse.jdt.internal.compiler.util.*; | |
import org.eclipse.jdt.internal.codeassist.*; | |
import org.eclipse.jdt.core.*; | |
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; | |
/** | |
* This class provides a <code>SearchableBuilderEnvironment</code> for code assist which | |
* uses the Java model as a search tool. | |
*/ | |
public class SearchableEnvironment implements ISearchableNameEnvironment, IJavaSearchConstants { | |
protected NameLookup nameLookup; | |
protected ICompilationUnit unitToSkip; | |
public CompilationUnit unitToLookInside; | |
protected IJavaProject project; | |
/** | |
* Creates a SearchableEnvironment on the given project | |
*/ | |
public SearchableEnvironment(IJavaProject project) throws JavaModelException { | |
this.project = project; | |
this.nameLookup = (NameLookup)((JavaProject)project).getNameLookup(); | |
} | |
/** | |
* Returns the given type in the the given package if it exists, | |
* otherwise <code>null</code>. | |
*/ | |
protected NameEnvironmentAnswer find(String typeName, String packageName) { | |
if (packageName == null) | |
packageName = IPackageFragment.DEFAULT_PACKAGE_NAME; | |
IType type = this.nameLookup.findType(typeName, packageName, false, INameLookup.ACCEPT_CLASSES | INameLookup.ACCEPT_INTERFACES); | |
if (type == null) { | |
// look inside the compilation unit that is being searched currently | |
//for a non-public or inner type. | |
if (this.unitToLookInside != null) { | |
if (this.unitToLookInside.getParent().getElementName().equals(packageName)) { | |
try { | |
IType[] allTypes = this.unitToLookInside.getTypes(); | |
for (int i= 0; i < allTypes.length; i++) { | |
if (allTypes[i].getElementName().equals(typeName)) { | |
type = allTypes[i]; | |
break; | |
} | |
} | |
} catch (JavaModelException e) { | |
} | |
} | |
} | |
} | |
if (type != null) { | |
if (type instanceof BinaryType) { | |
try { | |
return new NameEnvironmentAnswer((IBinaryType) ((BinaryType) type).getRawInfo()); | |
} catch (JavaModelException npe) { | |
return null; | |
} | |
} else { //SourceType | |
try { | |
return new NameEnvironmentAnswer((ISourceType)((SourceType)type).getRawInfo()); | |
} catch (JavaModelException npe) { | |
return null; | |
} | |
} | |
} | |
return null; | |
} | |
/** | |
* @see SearchableBuilderEnvironment | |
*/ | |
public void findPackages(char[] prefix, ISearchRequestor requestor) { | |
this.nameLookup.seekPackageFragments(new String(prefix), true, new SearchableEnvironmentRequestor(requestor)); | |
} | |
/** | |
* @see INameEnvironment | |
*/ | |
public NameEnvironmentAnswer findType(char[][] compoundTypeName) { | |
if (compoundTypeName == null) | |
return null; | |
int length = compoundTypeName.length; | |
if (length == 1) | |
return find(new String(compoundTypeName[0]), null); | |
StringBuffer buffer = new StringBuffer(length * 6); | |
int lengthM1 = length - 1; | |
for(int i = 0; i < lengthM1; i++) { | |
buffer.append(compoundTypeName[i]); | |
if (i + 1 != lengthM1) | |
buffer.append('.'); | |
} | |
String className = new String(compoundTypeName[lengthM1]); | |
return find(className, buffer.toString()); | |
} | |
/** | |
* @see INameEnvironment | |
*/ | |
public NameEnvironmentAnswer findType(char[] name, char[][] packages) { | |
if (name == null) | |
return null; | |
if (packages == null || packages.length == 0) | |
return find(new String(name), null); | |
int length = packages.length; | |
StringBuffer buffer = new StringBuffer(length * 6); | |
for(int i = 0; i < length; i++) { | |
buffer.append(packages[i]); | |
if (i + 1 != length) | |
buffer.append('.'); | |
} | |
String className = new String(name); | |
return find(className, buffer.toString()); | |
} | |
/** | |
* @see ISearchableNameEnvironment | |
*/ | |
public void findTypes(char[] prefix, final ISearchRequestor storage) { | |
/* | |
if (true){ | |
findTypes(new String(prefix), storage, INameLookup.ACCEPT_CLASSES | INameLookup.ACCEPT_INTERFACES); | |
return; | |
} | |
*/ | |
try { | |
final String excludePath; | |
if (this.unitToSkip != null){ | |
if (!(this.unitToSkip instanceof IJavaElement)){ // revert to model investigation | |
findTypes(new String(prefix), storage, INameLookup.ACCEPT_CLASSES | INameLookup.ACCEPT_INTERFACES); | |
return; | |
} | |
excludePath = ((IJavaElement)this.unitToSkip).getUnderlyingResource().getFullPath().toString(); | |
} else { | |
excludePath = null; | |
} | |
int lastDotIndex = CharOperation.lastIndexOf('.', prefix); | |
char[] qualification, simpleName; | |
if (lastDotIndex < 0){ | |
qualification = null; | |
simpleName = CharOperation.toLowerCase(prefix); | |
} else { | |
qualification = CharOperation.subarray(prefix, 0, lastDotIndex); | |
simpleName = CharOperation.toLowerCase(CharOperation.subarray(prefix, lastDotIndex+1, prefix.length)); | |
} | |
SearchEngine searchEngine = new SearchEngine(); | |
IProject projectRsc = (IProject) this.project.getUnderlyingResource(); | |
IJavaSearchScope scope = searchEngine.createJavaSearchScope(new IResource[]{ projectRsc}); | |
IProgressMonitor progressMonitor = new IProgressMonitor(){ | |
boolean isCanceled = false; | |
public void beginTask(String name, int totalWork){} | |
public void done(){} | |
public void internalWorked(double work){} | |
public boolean isCanceled(){ return isCanceled; } | |
public void setCanceled(boolean value){ isCanceled = value; } | |
public void setTaskName(String name){} | |
public void subTask(String name){} | |
public void worked(int work){} | |
}; | |
ITypeNameRequestor nameRequestor = new ITypeNameRequestor(){ | |
public void acceptClass(char[] packageName, char[] simpleTypeName, char[][] enclosingTypeNames, String path){ | |
if (excludePath != null && excludePath.equals(path)) return; | |
if (enclosingTypeNames != null && enclosingTypeNames.length > 0) return; // accept only top level types | |
storage.acceptClass(packageName, simpleTypeName, 0); | |
} | |
public void acceptInterface(char[] packageName, char[] simpleTypeName, char[][] enclosingTypeNames, String path){ | |
if (excludePath != null && excludePath.equals(path)) return; | |
if (enclosingTypeNames != null && enclosingTypeNames.length > 0) return; // accept only top level types | |
storage.acceptInterface(packageName, simpleTypeName, 0); | |
} | |
}; | |
try { | |
searchEngine.searchAllTypeNames( | |
projectRsc.getWorkspace(), | |
qualification, | |
simpleName, | |
PREFIX_MATCH, | |
CASE_INSENSITIVE, | |
IJavaSearchConstants.TYPE, | |
scope, | |
nameRequestor, | |
CANCEL_IF_NOT_READY_TO_SEARCH, | |
progressMonitor); | |
} catch (OperationCanceledException e) { | |
findTypes(new String(prefix), storage, INameLookup.ACCEPT_CLASSES | INameLookup.ACCEPT_INTERFACES); | |
} | |
} catch(JavaModelException e){ | |
findTypes(new String(prefix), storage, INameLookup.ACCEPT_CLASSES | INameLookup.ACCEPT_INTERFACES); | |
} | |
} | |
/** | |
* Returns all types whose name starts with the given (qualified) <code>prefix</code>. | |
* | |
* If the <code>prefix</code> is unqualified, all types whose simple name matches | |
* the <code>prefix</code> are returned. | |
*/ | |
private void findTypes(String prefix, ISearchRequestor storage, int type) { | |
SearchableEnvironmentRequestor requestor = new SearchableEnvironmentRequestor(storage, this.unitToSkip); | |
int index = prefix.lastIndexOf('.'); | |
if (index == -1) { | |
this.nameLookup.seekTypes(prefix, null, true, type, requestor); | |
} else { | |
String packageName = prefix.substring(0, index); | |
String className = prefix.substring(index + 1); | |
JavaElementRequestor javaElementRequestor = new JavaElementRequestor(); | |
this.nameLookup.seekPackageFragments(packageName, false, javaElementRequestor); | |
IPackageFragment[] packageFragments = javaElementRequestor.getPackageFragments(); | |
if (packageFragments == null) | |
return; | |
for (int i = 0, packagesLength = packageFragments.length; i < packagesLength; i++) { | |
if (packageFragments[i] == null) | |
continue; | |
this.nameLookup.seekTypes(className, packageFragments[i], true, type, requestor); | |
} | |
} | |
} | |
/** | |
* @see SearchableBuilderEnvironment | |
*/ | |
public boolean isPackage(char[][] parentPackageName, char[] subPackageName) { | |
if (parentPackageName == null || parentPackageName.length == 0) | |
return isTopLevelPackage(subPackageName); | |
if (subPackageName == null) | |
return false; | |
int length = parentPackageName.length; | |
StringBuffer buffer = new StringBuffer((length + 1) * 6); | |
for(int i = 0; i < length; i++) { | |
if (parentPackageName[i] == null || isQualified(parentPackageName[i])) | |
return false; | |
buffer.append(parentPackageName[i]); | |
buffer.append('.'); | |
} | |
if (isQualified(subPackageName)) { | |
return false; | |
} | |
buffer.append(subPackageName); | |
boolean result= this.nameLookup.findPackageFragments(buffer.toString(), false) != null; | |
return result; | |
} | |
/** | |
* Returns true if there are no '.' characters in the given name. | |
*/ | |
protected boolean isQualified(char[] name) { | |
if (name != null) { | |
return CharOperation.indexOf('.', name) > -1; | |
} | |
return false; | |
} | |
/** | |
* @see SearchableBuilderEnvironment | |
*/ | |
public boolean isTopLevelPackage(char[] packageName) { | |
if (packageName == null) | |
return false; | |
boolean result= !isQualified(packageName) | |
&& this.nameLookup.findPackageFragments(new String(packageName), false) != null; | |
return result; | |
} | |
/** | |
* Returns a printable string for the array. | |
*/ | |
protected String toStringChar(char[] name) { | |
return "["/*nonNLS*/ + new String(name) + "]"/*nonNLS*/; | |
} | |
/** | |
* Returns a printable string for the array. | |
*/ | |
protected String toStringCharChar(char[][] names) { | |
StringBuffer result= new StringBuffer(); | |
for (int i= 0; i < names.length; i++) { | |
result.append(toStringChar(names[i])); | |
} | |
return result.toString(); | |
} | |
} |