blob: d69cbf5e26ef0c1b6ad05795502ed03a50a0fb62 [file] [log] [blame]
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.*;
import org.eclipse.jdt.core.search.*;
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
import org.eclipse.jdt.internal.compiler.env.*;
import org.eclipse.jdt.internal.compiler.util.*;
import org.eclipse.jdt.internal.codeassist.*;
import org.eclipse.jdt.internal.core.SourceTypeElementInfo;;
/**
* 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 {
// retrieve the requested type
SourceTypeElementInfo sourceType = (SourceTypeElementInfo)((SourceType)type).getRawInfo();
ISourceType topLevelType = sourceType;
while (topLevelType.getEnclosingType() != null) {
topLevelType = topLevelType.getEnclosingType();
}
// find all siblings (other types declared in same unit, since may be used for name resolution)
IType[] types = sourceType.getHandle().getCompilationUnit().getTypes();
ISourceType[] sourceTypes = new ISourceType[types.length];
// in the resulting collection, ensure the requested type is the first one
sourceTypes[0] = sourceType;
for (int i = 0, index = 1; i < types.length; i++) {
ISourceType otherType =
(ISourceType) ((JavaElement) types[i]).getRawInfo();
if (!otherType.equals(topLevelType))
sourceTypes[index++] = otherType;
}
return new NameEnvironmentAnswer(sourceTypes);
} 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, IConstants.AccPublic);
}
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, IConstants.AccPublic);
}
};
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 "[" //$NON-NLS-1$
+ new String(name) + "]" ; //$NON-NLS-1$
}
/**
* 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();
}
}