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