6a405c97aaa3f0ffa3211fe63aafae632be055ca
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / core / SearchableEnvironment.java
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
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core;
12
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;
29
30 import org.eclipse.core.runtime.IProgressMonitor;
31
32 /**
33  * This class provides a <code>SearchableBuilderEnvironment</code> for code
34  * assist which uses the Java model as a search tool.
35  */
36 public class SearchableEnvironment implements ISearchableNameEnvironment,
37                 IJavaSearchConstants {
38         protected NameLookup nameLookup;
39
40         protected ICompilationUnit unitToSkip;
41
42         protected IJavaProject project;
43
44         // protected IJavaSearchScope searchScope;
45
46         /**
47          * Creates a Sea /** Creates a SearchableEnvironment on the given project
48          */
49         public SearchableEnvironment(IJavaProject project)
50                         throws JavaModelException {
51                 this.project = project;
52                 this.nameLookup = (NameLookup) ((JavaProject) project).getNameLookup();
53
54                 // Create search scope with visible entry on the project's classpath
55                 // this.searchScope =
56                 // SearchEngine.createJavaSearchScope(this.project.getAllPackageFragmentRoots());
57         }
58
59         /**
60          * Creates a SearchableEnvironment on the given project
61          */
62         public SearchableEnvironment(JavaProject project, WorkingCopyOwner owner)
63                         throws JavaModelException {
64                 this.project = project;
65                 this.nameLookup = project.newNameLookup(owner);
66
67                 // Create search scope with visible entry on the project's classpath
68                 // this.searchScope =
69                 // SearchEngine.createJavaSearchScope(this.project.getAllPackageFragmentRoots());
70         }
71
72         /**
73          * Returns the given type in the the given package if it exists, otherwise
74          * <code>null</code>.
75          */
76         protected NameEnvironmentAnswer find(String typeName, String packageName) {
77                 if (packageName == null)
78                         packageName = IPackageFragment.DEFAULT_PACKAGE_NAME;
79
80                 if (this.nameLookup != null) { // ins axelcl
81                         IType type = this.nameLookup.findType(typeName, packageName, false,
82                                         NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
83                         if (type != null) {
84                                 // if (type instanceof BinaryType) {
85                                 // try {
86                                 // return new NameEnvironmentAnswer(
87                                 // (IBinaryType) ((BinaryType) type).getElementInfo());
88                                 // } catch (JavaModelException npe) {
89                                 // return null;
90                                 // }
91                                 // } else { //SourceType
92                                 try {
93                                         // retrieve the requested type
94                                         SourceTypeElementInfo sourceType = (SourceTypeElementInfo) ((SourceType) type)
95                                                         .getElementInfo();
96                                         ISourceType topLevelType = sourceType;
97                                         while (topLevelType.getEnclosingType() != null) {
98                                                 topLevelType = topLevelType.getEnclosingType();
99                                         }
100                                         // find all siblings (other types declared in same unit,
101                                         // since may be used for name resolution)
102                                         IType[] types = sourceType.getHandle().getCompilationUnit()
103                                                         .getTypes();
104                                         ISourceType[] sourceTypes = new ISourceType[types.length];
105
106                                         // in the resulting collection, ensure the requested type is
107                                         // the first one
108                                         sourceTypes[0] = sourceType;
109                                         for (int i = 0, index = 1; i < types.length; i++) {
110                                                 ISourceType otherType = (ISourceType) ((JavaElement) types[i])
111                                                                 .getElementInfo();
112                                                 if (!otherType.equals(topLevelType))
113                                                         sourceTypes[index++] = otherType;
114                                         }
115                                         return new NameEnvironmentAnswer(sourceTypes);
116                                 } catch (JavaModelException npe) {
117                                         return null;
118                                 }
119                                 // }
120                         }
121                 }
122                 return null;
123         }
124
125         /**
126          * @see ISearchableNameEnvironment#findPackages(char[], ISearchRequestor)
127          */
128         public void findPackages(char[] prefix, ISearchRequestor requestor) {
129                 // this.nameLookup.seekPackageFragments(
130                 // new String(prefix),
131                 // true,
132                 // new SearchableEnvironmentRequestor(requestor));
133         }
134
135         /**
136          * @see INameEnvironment#findType(char[][])
137          */
138         public NameEnvironmentAnswer findType(char[][] compoundTypeName) {
139                 if (compoundTypeName == null)
140                         return null;
141
142                 int length = compoundTypeName.length;
143                 if (length <= 1) {
144                         if (length == 0)
145                                 return null;
146                         return find(new String(compoundTypeName[0]), null);
147                 }
148
149                 int lengthM1 = length - 1;
150                 char[][] packageName = new char[lengthM1][];
151                 System.arraycopy(compoundTypeName, 0, packageName, 0, lengthM1);
152
153                 return find(new String(compoundTypeName[lengthM1]), CharOperation
154                                 .toString(packageName));
155         }
156
157         /**
158          * @see INameEnvironment#findType(char[], char[][])
159          */
160         public NameEnvironmentAnswer findType(char[] name, char[][] packageName) {
161                 if (name == null)
162                         return null;
163
164                 return find(new String(name), packageName == null
165                                 || packageName.length == 0 ? null : CharOperation
166                                 .toString(packageName));
167         }
168
169         /**
170          * @see ISearchableNameEnvironment#findTypes(char[], ISearchRequestor)
171          */
172         public void findTypes(char[] prefix, final ISearchRequestor storage) {
173
174                 /*
175                  * if (true){ findTypes(new String(prefix), storage,
176                  * NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES); return; }
177                  */
178                 // try {
179                 final String excludePath;
180                 if (this.unitToSkip != null) {
181                         if (!(this.unitToSkip instanceof IJavaElement)) {
182                                 // revert to model investigation
183                                 findTypes(new String(prefix), storage,
184                                                 NameLookup.ACCEPT_CLASSES
185                                                                 | NameLookup.ACCEPT_INTERFACES);
186                                 return;
187                         }
188                         excludePath = ((IJavaElement) this.unitToSkip).getPath().toString();
189                 } else {
190                         excludePath = null;
191                 }
192                 int lastDotIndex = CharOperation.lastIndexOf('.', prefix);
193                 char[] qualification, simpleName;
194                 if (lastDotIndex < 0) {
195                         qualification = null;
196                         simpleName = CharOperation.toLowerCase(prefix);
197                 } else {
198                         qualification = CharOperation.subarray(prefix, 0, lastDotIndex);
199                         simpleName = CharOperation.toLowerCase(CharOperation.subarray(
200                                         prefix, lastDotIndex + 1, prefix.length));
201                 }
202
203                 IProgressMonitor progressMonitor = new IProgressMonitor() {
204                         boolean isCanceled = false;
205
206                         public void beginTask(String name, int totalWork) {
207                         }
208
209                         public void done() {
210                         }
211
212                         public void internalWorked(double work) {
213                         }
214
215                         public boolean isCanceled() {
216                                 return isCanceled;
217                         }
218
219                         public void setCanceled(boolean value) {
220                                 isCanceled = value;
221                         }
222
223                         public void setTaskName(String name) {
224                         }
225
226                         public void subTask(String name) {
227                         }
228
229                         public void worked(int work) {
230                         }
231                 };
232                 ITypeNameRequestor nameRequestor = new ITypeNameRequestor() {
233                         public void acceptClass(char[] packageName, char[] simpleTypeName,
234                                         char[][] enclosingTypeNames, String path) {
235                                 if (excludePath != null && excludePath.equals(path))
236                                         return;
237                                 if (enclosingTypeNames != null && enclosingTypeNames.length > 0)
238                                         return; // accept only top level types
239                                 storage.acceptClass(packageName, simpleTypeName,
240                                                 IConstants.AccPublic);
241                         }
242
243                         public void acceptInterface(char[] packageName,
244                                         char[] simpleTypeName, char[][] enclosingTypeNames,
245                                         String path) {
246                                 if (excludePath != null && excludePath.equals(path))
247                                         return;
248                                 if (enclosingTypeNames != null && enclosingTypeNames.length > 0)
249                                         return; // accept only top level types
250                                 storage.acceptInterface(packageName, simpleTypeName,
251                                                 IConstants.AccPublic);
252                         }
253                 };
254                 // try {
255                 // new SearchEngine().searchAllTypeNames(
256                 // this.project.getProject().getWorkspace(),
257                 // qualification,
258                 // simpleName,
259                 // PREFIX_MATCH,
260                 // CASE_INSENSITIVE,
261                 // IJavaSearchConstants.TYPE,
262                 // this.searchScope,
263                 // nameRequestor,
264                 // CANCEL_IF_NOT_READY_TO_SEARCH,
265                 // progressMonitor);
266                 // } catch (OperationCanceledException e) {
267                 // findTypes(
268                 // new String(prefix),
269                 // storage,
270                 // NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
271                 // }
272                 // } catch (JavaModelException e) {
273                 // findTypes(
274                 // new String(prefix),
275                 // storage,
276                 // NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
277                 // }
278         }
279
280         /**
281          * Returns all types whose name starts with the given (qualified)
282          * <code>prefix</code>.
283          * 
284          * If the <code>prefix</code> is unqualified, all types whose simple name
285          * matches the <code>prefix</code> are returned.
286          */
287         private void findTypes(String prefix, ISearchRequestor storage, int type) {
288                 SearchableEnvironmentRequestor requestor = new SearchableEnvironmentRequestor(
289                                 storage, this.unitToSkip);
290                 int index = prefix.lastIndexOf('.');
291                 if (index == -1) {
292                         this.nameLookup.seekTypes(prefix, null, true, type, requestor);
293                 } else {
294                         String packageName = prefix.substring(0, index);
295                         JavaElementRequestor elementRequestor = new JavaElementRequestor();
296                         this.nameLookup.seekPackageFragments(packageName, false,
297                                         elementRequestor);
298                         IPackageFragment[] fragments = elementRequestor
299                                         .getPackageFragments();
300                         if (fragments != null) {
301                                 String className = prefix.substring(index + 1);
302                                 for (int i = 0, length = fragments.length; i < length; i++)
303                                         if (fragments[i] != null)
304                                                 this.nameLookup.seekTypes(className, fragments[i],
305                                                                 true, type, requestor);
306                         }
307                 }
308         }
309
310         /**
311          * @see INameEnvironment#isPackage(char[][], char[])
312          */
313         public boolean isPackage(char[][] parentPackageName, char[] subPackageName) {
314                 if (subPackageName == null
315                                 || CharOperation.contains('.', subPackageName))
316                         return false;
317                 if (parentPackageName == null || parentPackageName.length == 0)
318                         return isTopLevelPackage(subPackageName);
319                 for (int i = 0, length = parentPackageName.length; i < length; i++)
320                         if (parentPackageName[i] == null
321                                         || CharOperation.contains('.', parentPackageName[i]))
322                                 return false;
323
324                 String packageName = new String(CharOperation.concatWith(
325                                 parentPackageName, subPackageName, '.'));
326                 return this.nameLookup.findPackageFragments(packageName, false) != null;
327         }
328
329         public boolean isTopLevelPackage(char[] packageName) {
330                 return packageName != null
331                                 && !CharOperation.contains('.', packageName)
332                                 && this.nameLookup.findPackageFragments(
333                                                 new String(packageName), false) != null;
334         }
335
336         /**
337          * Returns a printable string for the array.
338          */
339         protected String toStringChar(char[] name) {
340                 return "[" //$NON-NLS-1$
341                                 + new String(name) + "]"; //$NON-NLS-1$
342         }
343
344         /**
345          * Returns a printable string for the array.
346          */
347         protected String toStringCharChar(char[][] names) {
348                 StringBuffer result = new StringBuffer();
349                 for (int i = 0; i < names.length; i++) {
350                         result.append(toStringChar(names[i]));
351                 }
352                 return result.toString();
353         }
354
355         public void cleanup() {
356         }
357 }