1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core;
13 import net.sourceforge.phpdt.core.ICompilationUnit;
14 import net.sourceforge.phpdt.core.IJavaElement;
15 import net.sourceforge.phpdt.core.IJavaProject;
16 import net.sourceforge.phpdt.core.IPackageFragment;
17 import net.sourceforge.phpdt.core.IType;
18 import net.sourceforge.phpdt.core.JavaModelException;
19 import net.sourceforge.phpdt.core.WorkingCopyOwner;
20 import net.sourceforge.phpdt.core.compiler.CharOperation;
21 import net.sourceforge.phpdt.core.search.IJavaSearchConstants;
22 import net.sourceforge.phpdt.core.search.ITypeNameRequestor;
23 import net.sourceforge.phpdt.internal.codeassist.ISearchRequestor;
24 import net.sourceforge.phpdt.internal.codeassist.ISearchableNameEnvironment;
25 import net.sourceforge.phpdt.internal.compiler.env.IConstants;
26 import net.sourceforge.phpdt.internal.compiler.env.INameEnvironment;
27 import net.sourceforge.phpdt.internal.compiler.env.ISourceType;
28 import net.sourceforge.phpdt.internal.compiler.env.NameEnvironmentAnswer;
30 import org.eclipse.core.runtime.IProgressMonitor;
33 * This class provides a <code>SearchableBuilderEnvironment</code> for code assist which
34 * uses the Java model as a search tool.
36 public class SearchableEnvironment implements ISearchableNameEnvironment, IJavaSearchConstants {
37 protected NameLookup nameLookup;
38 protected ICompilationUnit unitToSkip;
40 protected IJavaProject project;
41 //protected IJavaSearchScope searchScope;
46 * Creates a SearchableEnvironment on the given project
48 public SearchableEnvironment(IJavaProject project) throws JavaModelException {
49 this.project = project;
50 this.nameLookup = (NameLookup) ((JavaProject) project).getNameLookup();
52 // Create search scope with visible entry on the project's classpath
53 // this.searchScope = SearchEngine.createJavaSearchScope(this.project.getAllPackageFragmentRoots());
59 * Creates a SearchableEnvironment on the given project
61 public SearchableEnvironment(JavaProject project, WorkingCopyOwner owner) throws JavaModelException {
62 this.project = project;
63 this.nameLookup = project.newNameLookup(owner);
65 // Create search scope with visible entry on the project's classpath
66 // this.searchScope = SearchEngine.createJavaSearchScope(this.project.getAllPackageFragmentRoots());
69 * Returns the given type in the the given package if it exists,
70 * otherwise <code>null</code>.
72 protected NameEnvironmentAnswer find(String typeName, String packageName) {
73 if (packageName == null)
74 packageName = IPackageFragment.DEFAULT_PACKAGE_NAME;
76 IType type = this.nameLookup.findType(typeName, packageName, false, NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
78 // if (type instanceof BinaryType) {
80 // return new NameEnvironmentAnswer(
81 // (IBinaryType) ((BinaryType) type).getElementInfo());
82 // } catch (JavaModelException npe) {
85 // } else { //SourceType
87 // retrieve the requested type
88 SourceTypeElementInfo sourceType = (SourceTypeElementInfo) ((SourceType) type).getElementInfo();
89 ISourceType topLevelType = sourceType;
90 while (topLevelType.getEnclosingType() != null) {
91 topLevelType = topLevelType.getEnclosingType();
93 // find all siblings (other types declared in same unit, since may be used for name resolution)
94 IType[] types = sourceType.getHandle().getCompilationUnit().getTypes();
95 ISourceType[] sourceTypes = new ISourceType[types.length];
97 // in the resulting collection, ensure the requested type is the first one
98 sourceTypes[0] = sourceType;
99 for (int i = 0, index = 1; i < types.length; i++) {
100 ISourceType otherType = (ISourceType) ((JavaElement) types[i]).getElementInfo();
101 if (!otherType.equals(topLevelType))
102 sourceTypes[index++] = otherType;
104 return new NameEnvironmentAnswer(sourceTypes);
105 } catch (JavaModelException npe) {
114 * @see ISearchableNameEnvironment#findPackages(char[], ISearchRequestor)
116 public void findPackages(char[] prefix, ISearchRequestor requestor) {
117 // this.nameLookup.seekPackageFragments(
118 // new String(prefix),
120 // new SearchableEnvironmentRequestor(requestor));
124 * @see INameEnvironment#findType(char[][])
126 public NameEnvironmentAnswer findType(char[][] compoundTypeName) {
127 if (compoundTypeName == null)
130 int length = compoundTypeName.length;
134 return find(new String(compoundTypeName[0]), null);
137 int lengthM1 = length - 1;
138 char[][] packageName = new char[lengthM1][];
139 System.arraycopy(compoundTypeName, 0, packageName, 0, lengthM1);
141 return find(new String(compoundTypeName[lengthM1]), CharOperation.toString(packageName));
145 * @see INameEnvironment#findType(char[], char[][])
147 public NameEnvironmentAnswer findType(char[] name, char[][] packageName) {
151 return find(new String(name), packageName == null || packageName.length == 0 ? null : CharOperation.toString(packageName));
155 * @see ISearchableNameEnvironment#findTypes(char[], ISearchRequestor)
157 public void findTypes(char[] prefix, final ISearchRequestor storage) {
161 findTypes(new String(prefix), storage, NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
166 final String excludePath;
167 if (this.unitToSkip != null) {
168 if (!(this.unitToSkip instanceof IJavaElement)) {
169 // revert to model investigation
170 findTypes(new String(prefix), storage, NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
173 excludePath = ((IJavaElement) this.unitToSkip).getPath().toString();
177 int lastDotIndex = CharOperation.lastIndexOf('.', prefix);
178 char[] qualification, simpleName;
179 if (lastDotIndex < 0) {
180 qualification = null;
181 simpleName = CharOperation.toLowerCase(prefix);
183 qualification = CharOperation.subarray(prefix, 0, lastDotIndex);
184 simpleName = CharOperation.toLowerCase(CharOperation.subarray(prefix, lastDotIndex + 1, prefix.length));
187 IProgressMonitor progressMonitor = new IProgressMonitor() {
188 boolean isCanceled = false;
189 public void beginTask(String name, int totalWork) {
193 public void internalWorked(double work) {
195 public boolean isCanceled() {
198 public void setCanceled(boolean value) {
201 public void setTaskName(String name) {
203 public void subTask(String name) {
205 public void worked(int work) {
208 ITypeNameRequestor nameRequestor = new ITypeNameRequestor() {
209 public void acceptClass(char[] packageName, char[] simpleTypeName, char[][] enclosingTypeNames, String path) {
210 if (excludePath != null && excludePath.equals(path))
212 if (enclosingTypeNames != null && enclosingTypeNames.length > 0)
213 return; // accept only top level types
214 storage.acceptClass(packageName, simpleTypeName, IConstants.AccPublic);
216 public void acceptInterface(char[] packageName, char[] simpleTypeName, char[][] enclosingTypeNames, String path) {
217 if (excludePath != null && excludePath.equals(path))
219 if (enclosingTypeNames != null && enclosingTypeNames.length > 0)
220 return; // accept only top level types
221 storage.acceptInterface(packageName, simpleTypeName, IConstants.AccPublic);
225 // new SearchEngine().searchAllTypeNames(
226 // this.project.getProject().getWorkspace(),
231 // IJavaSearchConstants.TYPE,
234 // CANCEL_IF_NOT_READY_TO_SEARCH,
236 // } catch (OperationCanceledException e) {
238 // new String(prefix),
240 // NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
242 // } catch (JavaModelException e) {
244 // new String(prefix),
246 // NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
251 * Returns all types whose name starts with the given (qualified) <code>prefix</code>.
253 * If the <code>prefix</code> is unqualified, all types whose simple name matches
254 * the <code>prefix</code> are returned.
256 private void findTypes(String prefix, ISearchRequestor storage, int type) {
257 SearchableEnvironmentRequestor requestor = new SearchableEnvironmentRequestor(storage, this.unitToSkip);
258 int index = prefix.lastIndexOf('.');
260 this.nameLookup.seekTypes(prefix, null, true, type, requestor);
262 String packageName = prefix.substring(0, index);
263 JavaElementRequestor elementRequestor = new JavaElementRequestor();
264 this.nameLookup.seekPackageFragments(packageName, false, elementRequestor);
265 IPackageFragment[] fragments = elementRequestor.getPackageFragments();
266 if (fragments != null) {
267 String className = prefix.substring(index + 1);
268 for (int i = 0, length = fragments.length; i < length; i++)
269 if (fragments[i] != null)
270 this.nameLookup.seekTypes(className, fragments[i], true, type, requestor);
276 * @see INameEnvironment#isPackage(char[][], char[])
278 public boolean isPackage(char[][] parentPackageName, char[] subPackageName) {
279 if (subPackageName == null || CharOperation.contains('.', subPackageName))
281 if (parentPackageName == null || parentPackageName.length == 0)
282 return isTopLevelPackage(subPackageName);
283 for (int i = 0, length = parentPackageName.length; i < length; i++)
284 if (parentPackageName[i] == null || CharOperation.contains('.', parentPackageName[i]))
287 String packageName = new String(CharOperation.concatWith(parentPackageName, subPackageName, '.'));
288 return this.nameLookup.findPackageFragments(packageName, false) != null;
291 public boolean isTopLevelPackage(char[] packageName) {
292 return packageName != null
293 && !CharOperation.contains('.', packageName)
294 && this.nameLookup.findPackageFragments(new String(packageName), false) != null;
298 * Returns a printable string for the array.
300 protected String toStringChar(char[] name) {
301 return "[" //$NON-NLS-1$
302 + new String(name) + "]"; //$NON-NLS-1$
306 * Returns a printable string for the array.
308 protected String toStringCharChar(char[][] names) {
309 StringBuffer result = new StringBuffer();
310 for (int i = 0; i < names.length; i++) {
311 result.append(toStringChar(names[i]));
313 return result.toString();
316 public void cleanup() {