Changes:
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / corext / template / php / JavaContext.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.corext.template.php;
12
13 import java.lang.reflect.InvocationTargetException;
14
15 import net.sourceforge.phpdt.core.ICompilationUnit;
16 import net.sourceforge.phpdt.core.JavaModelException;
17 import net.sourceforge.phpdt.internal.corext.Assert;
18 import net.sourceforge.phpdt.internal.corext.template.ContextType;
19 import net.sourceforge.phpdt.internal.corext.template.ContextTypeRegistry;
20 import net.sourceforge.phpdt.internal.corext.template.Template;
21 import net.sourceforge.phpdt.internal.corext.template.TemplateBuffer;
22 import net.sourceforge.phpdt.internal.corext.template.TemplateTranslator;
23 import net.sourceforge.phpdt.internal.corext.template.php.CompilationUnitCompletion.LocalVariable;
24 import net.sourceforge.phpdt.internal.ui.util.ExceptionHandler;
25 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
26
27 import org.eclipse.core.runtime.CoreException;
28 import org.eclipse.core.runtime.IStatus;
29 import org.eclipse.core.runtime.Status;
30 import org.eclipse.jface.dialogs.MessageDialog;
31 import org.eclipse.jface.preference.IPreferenceStore;
32 import org.eclipse.jface.text.BadLocationException;
33 import org.eclipse.jface.text.Document;
34 import org.eclipse.jface.text.IDocument;
35 import org.eclipse.swt.widgets.Shell;
36
37 /**
38  * A context for java source.
39  */
40 public class JavaContext extends PHPUnitContext {
41
42         /** The platform default line delimiter. */
43         private static final String PLATFORM_LINE_DELIMITER= System.getProperty("line.separator"); //$NON-NLS-1$
44
45         /** A code completion requestor for guessing local variable names. */
46         private CompilationUnitCompletion fCompletion;
47         
48         /**
49          * Creates a java template context.
50          * 
51          * @param type   the context type.
52          * @param document the document.
53          * @param completionOffset the completion offset within the document.
54          * @param completionLength the completion length.
55          * @param unit the compilation unit (may be <code>null</code>).
56          */
57         public JavaContext(ContextType type, IDocument document, int completionOffset, int completionLength,
58                 ICompilationUnit compilationUnit)
59         {
60                 super(type, document, completionOffset, completionLength); //, compilationUnit);
61         }
62         
63         /**
64          * Returns the indentation level at the position of code completion.
65          */
66         private int getIndentation() {
67 //              int start= getStart();
68 //              IDocument document= getDocument();
69 //              try {
70 //                      IRegion region= document.getLineInformationOfOffset(start);
71 //                      String lineContent= document.get(region.getOffset(), region.getLength());
72 //                      return Strings.computeIndent(lineContent, CodeFormatterUtil.getTabWidth());
73 //              } catch (BadLocationException e) {
74 //                      return 0;
75 //              }
76 return 0;
77         }       
78         
79         /*
80          * @see TemplateContext#evaluate(Template template)
81          */
82         public TemplateBuffer evaluate(Template template) throws CoreException {
83
84                 if (!canEvaluate(template))
85                         return null;
86                 
87                 TemplateTranslator translator= new TemplateTranslator();
88                 TemplateBuffer buffer= translator.translate(template.getPattern());
89
90                 getContextType().edit(buffer, this);
91                         
92                 String lineDelimiter= null;
93                 try {
94                         lineDelimiter= getDocument().getLineDelimiter(0);
95                 } catch (BadLocationException e) {
96                 }
97
98                 if (lineDelimiter == null)
99                         lineDelimiter= PLATFORM_LINE_DELIMITER;
100                         
101                 IPreferenceStore prefs= PHPeclipsePlugin.getDefault().getPreferenceStore();
102 //              boolean useCodeFormatter= prefs.getBoolean(PreferenceConstants.TEMPLATES_USE_CODEFORMATTER);                    
103 //              
104 //              ITemplateEditor formatter= new JavaFormatter(lineDelimiter, getIndentation(), useCodeFormatter);
105 //              formatter.edit(buffer, this);
106
107                 return buffer;
108         }
109         
110         /*
111          * @see TemplateContext#canEvaluate(Template templates)
112          */
113         public boolean canEvaluate(Template template) {
114                 String key= getKey();
115
116                 if (fForceEvaluation)
117                         return true;
118
119                 return
120                         template.matches(key, getContextType().getName()) &&
121                         key.length() != 0 && template.getName().toLowerCase().startsWith(key.toLowerCase());
122         }
123
124         /*
125          * @see DocumentTemplateContext#getCompletionPosition();
126          */
127         public int getStart() {
128
129                 try {
130                         IDocument document= getDocument();
131
132                         if (getCompletionLength() == 0) {
133
134                                 int start= getCompletionOffset();               
135                                 while ((start != 0) && Character.isUnicodeIdentifierPart(document.getChar(start - 1)))
136                                         start--;
137                                         
138                                 if ((start != 0) && Character.isUnicodeIdentifierStart(document.getChar(start - 1)))
139                                         start--;
140                 
141                                 return start;
142                         
143                         } else {
144
145                                 int start= getCompletionOffset();
146                                 int end= getCompletionOffset() + getCompletionLength();
147                                 
148                                 while (start != 0 && Character.isUnicodeIdentifierPart(document.getChar(start - 1)))
149                                         start--;
150                                 
151                                 while (start != end && Character.isWhitespace(document.getChar(start)))
152                                         start++;
153                                 
154                                 if (start == end)
155                                         start= getCompletionOffset();   
156                                 
157                                 return start;   
158                         }
159
160                 } catch (BadLocationException e) {
161                         return super.getStart();        
162                 }
163         }
164
165         /*
166          * @see org.eclipse.jdt.internal.corext.template.DocumentTemplateContext#getEnd()
167          */
168         public int getEnd() {
169                 
170                 if (getCompletionLength() == 0)         
171                         return super.getEnd();
172
173                 try {                   
174                         IDocument document= getDocument();
175
176                         int start= getCompletionOffset();
177                         int end= getCompletionOffset() + getCompletionLength();
178                         
179                         while (start != end && Character.isWhitespace(document.getChar(end - 1)))
180                                 end--;
181                         
182                         return end;     
183
184                 } catch (BadLocationException e) {
185                         return super.getEnd();
186                 }               
187         }
188
189         /*
190          * @see org.eclipse.jdt.internal.corext.template.DocumentTemplateContext#getKey()
191          */
192         public String getKey() {
193
194                 if (getCompletionLength() == 0)         
195                         return super.getKey();
196
197                 try {
198                         IDocument document= getDocument();
199
200                         int start= getStart();
201                         int end= getCompletionOffset();
202                         return start <= end
203                                 ? document.get(start, end - start)
204                                 : ""; //$NON-NLS-1$
205                         
206                 } catch (BadLocationException e) {
207                         return super.getKey();                  
208                 }
209         }
210
211         /**
212          * Returns the character before start position of completion.
213          */
214         public char getCharacterBeforeStart() {
215                 int start= getStart();
216                 
217                 try {
218                         return start == 0
219                                 ? ' '
220                                 : getDocument().getChar(start - 1);
221
222                 } catch (BadLocationException e) {
223                         return ' ';
224                 }
225         }
226
227         private CompilationUnitCompletion guessVariableNames() {
228 //              ICompilationUnit unit= getCompilationUnit();
229 //              int start= getStart();
230 //              
231 //              if (unit == null)
232 //                      return null;
233 //              
234 //              try {
235 //                      CompilationUnitCompletion collector= new CompilationUnitCompletion(unit);
236 //                      unit.codeComplete(start, collector);                    
237 //                      return collector;
238 //              
239 //              } catch (JavaModelException e) {
240 //                      handleException(null, e);
241 //                      return null;
242 //              }
243     return null;
244         }       
245         
246         
247         private static void handleException(Shell shell, Exception e) {
248                 String title= PHPTemplateMessages.getString("JavaContext.error.title"); //$NON-NLS-1$
249                 if (e instanceof CoreException)
250                         ExceptionHandler.handle((CoreException)e, shell, title, null);
251                 else if (e instanceof InvocationTargetException)
252                         ExceptionHandler.handle((InvocationTargetException)e, shell, title, null);
253                 else {
254                         PHPeclipsePlugin.log(e);
255                         MessageDialog.openError(shell, title, e.getMessage());
256                 }
257         }       
258
259         private CompilationUnitCompletion getCompletion() {
260 //              ICompilationUnit compilationUnit= getCompilationUnit();
261 //              if (fCompletion == null) {
262 //                      fCompletion= new CompilationUnitCompletion(compilationUnit);
263 //                      
264 //                      if (compilationUnit != null) {
265 //                              try {
266 //                                      compilationUnit.codeComplete(getStart(), fCompletion);
267 //                              } catch (JavaModelException e) {
268 //                                      // ignore
269 //                              }
270 //                      }
271 //              }
272 //              
273 //              return fCompletion;
274     return null;
275         }
276
277         /**
278          * Returns the name of a guessed local array, <code>null</code> if no local
279          * array exists.
280          */
281         public String guessArray() {
282                 CompilationUnitCompletion completion= getCompletion();
283                 LocalVariable[] localArrays= completion.findLocalArrays();
284                                 
285                 if (localArrays.length > 0)
286                         return localArrays[localArrays.length - 1].name;
287
288                 return null;    
289         }
290         
291         /**
292          * Returns the name of the type of a local array, <code>null</code> if no local
293          * array exists.
294          */
295         public String guessArrayType() {
296                 CompilationUnitCompletion completion= getCompletion();
297                 LocalVariable[] localArrays= completion.findLocalArrays();
298                                 
299                 if (localArrays.length > 0) {
300                         LocalVariable localArray= localArrays[localArrays.length - 1];                  
301
302                         String arrayTypeName= localArray.typeName;
303                         String typeName= getScalarType(arrayTypeName);
304                         int dimension= getArrayDimension(arrayTypeName) - 1;
305                         Assert.isTrue(dimension >= 0);
306                         
307                         String qualifiedName= createQualifiedTypeName(localArray.typePackageName, typeName);
308                         String innerTypeName= completion.simplifyTypeName(qualifiedName);
309                         
310                         return innerTypeName == null
311                                 ? createArray(typeName, dimension)
312                                 : createArray(innerTypeName, dimension);
313                 }
314                 
315                 return null;
316         }
317         
318         private static String createArray(String type, int dimension) {
319                 StringBuffer buffer= new StringBuffer(type);
320                 for (int i= 0; i < dimension; i++)
321                         buffer.append("[]"); //$NON-NLS-1$
322                 return buffer.toString();
323         }
324
325         private static String getScalarType(String type) {
326                 return type.substring(0, type.indexOf('['));
327         }
328         
329         private static int getArrayDimension(String type) {
330
331                 int dimension= 0;               
332                 int index= type.indexOf('[');
333
334                 while (index != -1) {
335                         dimension++;
336                         index= type.indexOf('[', index + 1);    
337                 }
338                 
339                 return dimension;               
340         }
341
342         private static String createQualifiedTypeName(String packageName, String className) {
343                 StringBuffer buffer= new StringBuffer();
344
345                 if (packageName.length() != 0) {
346                         buffer.append(packageName);
347                         buffer.append('.');
348                 }
349                 buffer.append(className);
350                 
351                 return buffer.toString();
352         }
353         
354         /**
355          * Returns a proposal for a variable name of a local array element, <code>null</code>
356          * if no local array exists.
357          */
358         public String guessArrayElement() {
359 //              CompilationUnitCompletion completion= getCompletion();
360 //              LocalVariable[] localArrays= completion.findLocalArrays();
361 //              
362 //              if (localArrays.length > 0) {
363 //                      int idx= localArrays.length - 1;
364 //                      
365 //                      LocalVariable var= localArrays[idx];
366 //                      
367 //                      IJavaProject project= getCompilationUnit().getJavaProject();
368 //                      String typeName= var.typeName;
369 //                      String baseTypeName= typeName.substring(0, typeName.lastIndexOf('['));
370 //
371 //                      String[] proposals= NamingConventions.suggestLocalVariableNames(project, var.typePackageName, baseTypeName, 0, completion.getLocalVariableNames());
372 //                      if (proposals.length > 0) {
373 //                              return proposals[0];
374 //                      }
375 //              }
376
377                 return null;
378         }
379
380         /**
381          * Returns an array index name. 'i', 'j', 'k' are tried until no name collision with
382          * an existing local variable occurs. If all names collide, <code>null</code> is returned.
383          */     
384         public String getIndex() {
385                 CompilationUnitCompletion completion= getCompletion();
386                 String[] proposals= {"i", "j", "k"};  //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
387                 
388                 for (int i= 0; i != proposals.length; i++) {
389                         String proposal = proposals[i];
390
391                         if (!completion.existsLocalName(proposal))
392                                 return proposal;
393                 }
394
395                 return null;
396         }
397         
398         /**
399          * Returns the name of a local collection, <code>null</code> if no local collection
400          * exists.
401          */
402         public String guessCollection() {
403                 CompilationUnitCompletion completion= getCompletion();
404                 try {
405                         LocalVariable[] localCollections= completion.findLocalCollections();
406                 
407                         if (localCollections.length > 0)
408                                 return localCollections[localCollections.length - 1].name;
409
410                 } catch (JavaModelException e) {
411                         PHPeclipsePlugin.log(e);
412                 }
413
414                 return null;
415         }
416
417         /**
418          * Returns an iterator name ('iter'). If 'iter' already exists as local variable,
419          * <code>null</code> is returned.
420          */
421         public String getIterator() {
422                 CompilationUnitCompletion completion= getCompletion();          
423                 String[] proposals= {"iter"}; //$NON-NLS-1$
424                 
425                 for (int i= 0; i != proposals.length; i++) {
426                         String proposal = proposals[i];
427
428                         if (!completion.existsLocalName(proposal))
429                                 return proposal;
430                 }
431
432                 return null;
433         }
434
435
436 //      public void addIteratorImport() {
437 //      
438 //              try {
439 //                      CodeGenerationSettings settings= JavaPreferencesSettings.getCodeGenerationSettings();
440 //                      ImportsStructure structure= new ImportsStructure(getCompilationUnit(), settings.importOrder, settings.importThreshold, true);
441 //                      structure.addImport("java.util.Iterator"); //$NON-NLS-1$
442 //                      structure.create(false, null);
443 //
444 //              } catch (CoreException e) {
445 //                      handleException(null, e);
446 //              }
447 //      }
448         
449         /**
450          * Evaluates a 'java' template in thecontext of a compilation unit
451          */
452         public static String evaluateTemplate(Template template, ICompilationUnit compilationUnit, int position) throws CoreException {
453
454                 ContextType contextType= ContextTypeRegistry.getInstance().getContextType("php"); //$NON-NLS-1$
455                 if (contextType == null)
456                         throw new CoreException(new Status(IStatus.ERROR, PHPeclipsePlugin.PLUGIN_ID, IStatus.ERROR, PHPTemplateMessages.getString("JavaContext.error.message"), null)); //$NON-NLS-1$
457
458                 IDocument document= new Document();
459 //              if (compilationUnit != null && compilationUnit.exists())
460 //                      document.set(compilationUnit.getSource());
461
462                 JavaContext context= new JavaContext(contextType, document, position, 0, compilationUnit);
463                 context.setForceEvaluation(true);
464
465                 TemplateBuffer buffer= context.evaluate(template);
466                 if (buffer == null)
467                         return null;
468                 return buffer.getString();
469         }
470
471 }
472