1 /*******************************************************************************
2 * Copyright (c) 2000, 2004 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.corext.template.php;
13 //import java.lang.reflect.InvocationTargetException;
15 import net.sourceforge.phpdt.core.ICompilationUnit;
16 //import net.sourceforge.phpdt.internal.corext.Assert;
17 //import net.sourceforge.phpdt.internal.corext.template.php.CompilationUnitCompletion.LocalVariable;
18 import net.sourceforge.phpdt.internal.corext.util.Strings;
19 import net.sourceforge.phpdt.internal.ui.preferences.CodeFormatterPreferencePage;
20 import net.sourceforge.phpdt.internal.ui.text.template.contentassist.MultiVariable;
21 //import net.sourceforge.phpdt.internal.ui.util.ExceptionHandler;
22 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
23 import net.sourceforge.phpeclipse.ui.WebUI;
25 import org.eclipse.core.runtime.CoreException;
26 import org.eclipse.core.runtime.IStatus;
27 import org.eclipse.core.runtime.Status;
28 //import org.eclipse.jface.dialogs.MessageDialog;
29 //import org.eclipse.jface.preference.IPreferenceStore;
30 import org.eclipse.jface.text.BadLocationException;
31 import org.eclipse.jface.text.Document;
32 import org.eclipse.jface.text.IDocument;
33 import org.eclipse.jface.text.IRegion;
34 import org.eclipse.jface.text.templates.Template;
35 import org.eclipse.jface.text.templates.TemplateBuffer;
36 import org.eclipse.jface.text.templates.TemplateContextType;
37 import org.eclipse.jface.text.templates.TemplateException;
38 import org.eclipse.jface.text.templates.TemplateTranslator;
39 import org.eclipse.jface.text.templates.TemplateVariable;
40 //import org.eclipse.swt.widgets.Shell;
43 * A context for java source.
45 public class JavaContext extends CompilationUnitContext {
47 /** The platform default line delimiter. */
48 private static final String PLATFORM_LINE_DELIMITER = System
49 .getProperty("line.separator"); //$NON-NLS-1$
51 /** A code completion requestor for guessing local variable names. */
52 //private CompilationUnitCompletion fCompletion;
55 * Creates a java template context.
61 * @param completionOffset
62 * the completion offset within the document.
63 * @param completionLength
64 * the completion length.
65 * @param compilationUnit
66 * the compilation unit (may be <code>null</code>).
68 public JavaContext(TemplateContextType type, IDocument document,
69 int completionOffset, int completionLength,
70 ICompilationUnit compilationUnit) {
71 super(type, document, completionOffset, completionLength,
76 * Returns the indentation level at the position of code completion.
78 private int getIndentation() {
79 int start = getStart();
80 IDocument document = getDocument();
82 IRegion region = document.getLineInformationOfOffset(start);
83 String lineContent = document.get(region.getOffset(), region
85 return Strings.computeIndent(lineContent,
86 CodeFormatterPreferencePage.getTabSize());
87 // return Strings.computeIndent(lineContent,
88 // CodeFormatterUtil.getTabWidth());
89 } catch (BadLocationException e) {
95 * @see TemplateContext#evaluate(Template template)
97 public TemplateBuffer evaluate(Template template)
98 throws BadLocationException, TemplateException {
100 if (!canEvaluate(template))
101 throw new TemplateException(JavaTemplateMessages
102 .getString("Context.error.cannot.evaluate")); //$NON-NLS-1$
104 TemplateTranslator translator = new TemplateTranslator() {
106 * @see org.eclipse.jface.text.templates.TemplateTranslator#createVariable(java.lang.String,
107 * java.lang.String, int[])
109 protected TemplateVariable createVariable(String type, String name,
111 return new MultiVariable(type, name, offsets);
114 TemplateBuffer buffer = translator.translate(template);
116 getContextType().resolve(buffer, this);
117 String lineDelimiter = null;
119 lineDelimiter = getDocument().getLineDelimiter(0);
120 } catch (BadLocationException e) {
123 if (lineDelimiter == null)
124 lineDelimiter = PLATFORM_LINE_DELIMITER;
125 // IPreferenceStore prefs = WebUI.getDefault()
126 // .getPreferenceStore();
128 // boolean useCodeFormatter =
129 // prefs.getBoolean(PreferenceConstants.TEMPLATES_USE_CODEFORMATTER);
130 boolean useCodeFormatter = false;
133 JavaFormatter formatter = new JavaFormatter(lineDelimiter,
134 getIndentation(), useCodeFormatter);
135 formatter.format(buffer, this);
137 // String res = buffer.getString();
138 // res = res.replaceAll("\n","/n");
139 // res = res.replaceAll("\t","/t");
140 // System.out.println(res);
146 * @see TemplateContext#canEvaluate(Template templates)
148 public boolean canEvaluate(Template template) {
149 String key = getKey();
151 if (fForceEvaluation)
154 return template.matches(key, getContextType().getId())
156 && template.getName().toLowerCase().startsWith(
160 public boolean canEvaluate(String identifier) {
161 String prefix = getKey();
162 return identifier.toLowerCase().startsWith(prefix.toLowerCase());
166 * @see DocumentTemplateContext#getCompletionPosition();
168 public int getStart() {
171 IDocument document = getDocument();
173 if (getCompletionLength() == 0) {
175 int start = getCompletionOffset();
177 && Character.isUnicodeIdentifierPart(document
178 .getChar(start - 1)))
182 && (Character.isUnicodeIdentifierStart(document
183 .getChar(start - 1)) || (document
184 .getChar(start - 1) == '$')))
191 int start = getCompletionOffset();
192 int end = getCompletionOffset() + getCompletionLength();
195 && Character.isUnicodeIdentifierPart(document
196 .getChar(start - 1)))
199 && (Character.isUnicodeIdentifierStart(document
200 .getChar(start - 1)) || (document
201 .getChar(start - 1) == '$')))
204 && Character.isWhitespace(document.getChar(start)))
208 start = getCompletionOffset();
213 } catch (BadLocationException e) {
214 return super.getStart();
219 * @see net.sourceforge.phpdt.internal.corext.template.DocumentTemplateContext#getEnd()
221 public int getEnd() {
223 if (getCompletionLength() == 0)
224 return super.getEnd();
227 IDocument document = getDocument();
229 int start = getCompletionOffset();
230 int end = getCompletionOffset() + getCompletionLength();
233 && Character.isWhitespace(document.getChar(end - 1)))
238 } catch (BadLocationException e) {
239 return super.getEnd();
244 * @see net.sourceforge.phpdt.internal.corext.template.DocumentTemplateContext#getKey()
246 public String getKey() {
248 // if (getCompletionLength() == 0) {
249 // return super.getKey();
253 IDocument document = getDocument();
255 int start = getStart();
256 int end = getCompletionOffset();
257 return start <= end ? document.get(start, end - start) : ""; //$NON-NLS-1$
259 } catch (BadLocationException e) {
260 return super.getKey();
265 * Returns the character before start position of completion.
267 public char getCharacterBeforeStart() {
268 int start = getStart();
271 return start == 0 ? ' ' : getDocument().getChar(start - 1);
273 } catch (BadLocationException e) {
278 // private static void handleException(Shell shell, Exception e) {
279 // String title = JavaTemplateMessages
280 // .getString("JavaContext.error.title"); //$NON-NLS-1$
281 // if (e instanceof CoreException)
282 // ExceptionHandler.handle((CoreException) e, shell, title, null);
283 // else if (e instanceof InvocationTargetException)
284 // ExceptionHandler.handle((InvocationTargetException) e, shell,
287 // PHPeclipsePlugin.log(e);
288 // MessageDialog.openError(shell, title, e.getMessage());
292 // private CompilationUnitCompletion getCompletion() {
293 // ICompilationUnit compilationUnit= getCompilationUnit();
294 // if (fCompletion == null) {
295 // fCompletion= new CompilationUnitCompletion(compilationUnit);
297 // if (compilationUnit != null) {
299 // compilationUnit.codeComplete(getStart(), fCompletion);
300 // } catch (JavaModelException e) {
306 // return fCompletion;
310 * Returns the name of a guessed local array, <code>null</code> if no
311 * local array exists.
313 // public String guessArray() {
314 // return firstOrNull(guessArrays());
317 * Returns the name of a guessed local array, <code>null</code> if no
318 * local array exists.
320 // public String[] guessArrays() {
321 // CompilationUnitCompletion completion= getCompletion();
322 // LocalVariable[] localArrays= completion.findLocalArrays();
324 // String[] ret= new String[localArrays.length];
325 // for (int i= 0; i < ret.length; i++) {
326 // ret[ret.length - i - 1]= localArrays[i].name;
331 * Returns the name of the type of a local array, <code>null</code> if no
332 * local array exists.
334 // public String guessArrayType() {
335 // return firstOrNull(guessArrayTypes());
337 // private String firstOrNull(String[] strings) {
338 // if (strings.length > 0)
339 // return strings[0];
345 * Returns the name of the type of a local array, <code>null</code> if no
346 * local array exists.
348 // public String[][] guessGroupedArrayTypes() {
349 // CompilationUnitCompletion completion= getCompletion();
350 // LocalVariable[] localArrays= completion.findLocalArrays();
352 // String[][] ret= new String[localArrays.length][];
354 // for (int i= 0; i < localArrays.length; i++) {
355 // String type= getArrayTypeFromLocalArray(completion,
356 // localArrays[localArrays.length - i - 1]);
357 // ret[i]= new String[] {type};
363 * Returns the name of the type of a local array, <code>null</code> if no
364 * local array exists.
366 // public String[] guessArrayTypes() {
367 // CompilationUnitCompletion completion= getCompletion();
368 // LocalVariable[] localArrays= completion.findLocalArrays();
370 // List ret= new ArrayList();
372 // for (int i= 0; i < localArrays.length; i++) {
373 // String type= getArrayTypeFromLocalArray(completion,
374 // localArrays[localArrays.length - i - 1]);
375 // if (!ret.contains(type))
379 // return (String[]) ret.toArray(new String[ret.size()]);
381 // private String getArrayTypeFromLocalArray(
382 // CompilationUnitCompletion completion, LocalVariable array) {
383 // String arrayTypeName = array.typeName;
384 // String typeName = getScalarType(arrayTypeName);
385 // int dimension = getArrayDimension(arrayTypeName) - 1;
386 // Assert.isTrue(dimension >= 0);
388 // String qualifiedName = createQualifiedTypeName(array.typePackageName,
390 // String innerTypeName = completion.simplifyTypeName(qualifiedName);
392 // return innerTypeName == null ? createArray(typeName, dimension)
393 // : createArray(innerTypeName, dimension);
396 // private static String createArray(String type, int dimension) {
397 // StringBuffer buffer = new StringBuffer(type);
398 // for (int i = 0; i < dimension; i++)
399 // buffer.append("[]"); //$NON-NLS-1$
400 // return buffer.toString();
403 // private static String getScalarType(String type) {
404 // return type.substring(0, type.indexOf('['));
407 // private static int getArrayDimension(String type) {
409 // int dimension = 0;
410 // int index = type.indexOf('[');
412 // while (index != -1) {
414 // index = type.indexOf('[', index + 1);
420 // private static String createQualifiedTypeName(String packageName,
421 // String className) {
422 // StringBuffer buffer = new StringBuffer();
424 // if (packageName.length() != 0) {
425 // buffer.append(packageName);
426 // buffer.append('.');
428 // buffer.append(className);
430 // return buffer.toString();
434 * Returns a proposal for a variable name of a local array element,
435 * <code>null</code> if no local array exists.
437 // public String guessArrayElement() {
438 // return firstOrNull(guessArrayElements());
441 * Returns a proposal for a variable name of a local array element,
442 * <code>null</code> if no local array exists.
444 // public String[] guessArrayElements() {
445 // ICompilationUnit cu= getCompilationUnit();
447 // return new String[0];
450 // CompilationUnitCompletion completion= getCompletion();
451 // LocalVariable[] localArrays= completion.findLocalArrays();
453 // List ret= new ArrayList();
455 // for (int i= 0; i < localArrays.length; i++) {
456 // int idx= localArrays.length - i - 1;
458 // LocalVariable var= localArrays[idx];
460 // IJavaProject project= cu.getJavaProject();
461 // String typeName= var.typeName;
462 // String baseTypeName= typeName.substring(0, typeName.lastIndexOf('['));
464 // String indexName= getIndex();
465 // String[] excludedNames= completion.getLocalVariableNames();
466 // if (indexName != null) {
467 // ArrayList excludedNamesList= new ArrayList(Arrays.asList(excludedNames));
468 // excludedNamesList.add(indexName);
469 // excludedNames= (String[])excludedNamesList.toArray(new
470 // String[excludedNamesList.size()]);
472 // String[] proposals= NamingConventions.suggestLocalVariableNames(project,
473 // var.typePackageName, baseTypeName, 0, excludedNames);
474 // for (int j= 0; j < proposals.length; j++) {
475 // if (!ret.contains(proposals[j]))
476 // ret.add(proposals[j]);
480 // return (String[]) ret.toArray(new String[ret.size()]);
483 * Returns a proposal for a variable name of a local array element,
484 * <code>null</code> if no local array exists.
486 // public String[][] guessGroupedArrayElements() {
487 // ICompilationUnit cu= getCompilationUnit();
489 // return new String[0][];
492 // CompilationUnitCompletion completion= getCompletion();
493 // LocalVariable[] localArrays= completion.findLocalArrays();
495 // String[][] ret= new String[localArrays.length][];
497 // for (int i= 0; i < localArrays.length; i++) {
498 // int idx= localArrays.length - i - 1;
500 // LocalVariable var= localArrays[idx];
502 // IJavaProject project= cu.getJavaProject();
503 // String typeName= var.typeName;
504 // int dim= -1; // we expect at least one array
505 // int lastIndex= typeName.length();
506 // int bracket= typeName.lastIndexOf('[');
507 // while (bracket != -1) {
508 // lastIndex= bracket;
510 // bracket= typeName.lastIndexOf('[', bracket - 1);
512 // typeName= typeName.substring(0, lastIndex);
514 // String indexName= getIndex();
515 // String[] excludedNames= completion.getLocalVariableNames();
516 // if (indexName != null) {
517 // ArrayList excludedNamesList= new ArrayList(Arrays.asList(excludedNames));
518 // excludedNamesList.add(indexName);
519 // excludedNames= (String[])excludedNamesList.toArray(new
520 // String[excludedNamesList.size()]);
522 // String[] proposals= NamingConventions.suggestLocalVariableNames(project,
523 // var.typePackageName, typeName, dim, excludedNames);
525 // ret[i]= proposals;
531 * Returns an array index name. 'i', 'j', 'k' are tried until no name
532 * collision with an existing local variable occurs. If all names collide,
533 * <code>null</code> is returned.
535 // public String getIndex() {
536 // CompilationUnitCompletion completion= getCompletion();
537 // String[] proposals= {"i", "j", "k"}; //$NON-NLS-1$ //$NON-NLS-2$
540 // for (int i= 0; i != proposals.length; i++) {
541 // String proposal = proposals[i];
543 // if (!completion.existsLocalName(proposal))
550 * Returns the name of a local collection, <code>null</code> if no local
553 // public String guessCollection() {
554 // return firstOrNull(guessCollections());
557 * Returns the names of local collections.
559 // public String[] guessCollections() {
560 // CompilationUnitCompletion completion= getCompletion();
562 // LocalVariable[] localCollections= completion.findLocalCollections();
563 // String[] ret= new String[localCollections.length];
564 // for (int i= 0; i < ret.length; i++) {
565 // ret[ret.length - i - 1]= localCollections[i].name;
570 // } catch (JavaModelException e) {
571 // JavaPlugin.log(e);
574 // return new String[0];
577 * Returns an iterator name ('iter'). If 'iter' already exists as local
578 * variable, <code>null</code> is returned.
580 // public String getIterator() {
581 // CompilationUnitCompletion completion= getCompletion();
582 // String[] proposals= {"iter"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
584 // for (int i= 0; i != proposals.length; i++) {
585 // String proposal = proposals[i];
587 // if (!completion.existsLocalName(proposal))
593 // public void addIteratorImport() {
594 // ICompilationUnit cu= getCompilationUnit();
600 // Position position= new Position(getCompletionOffset(),
601 // getCompletionLength());
602 // IDocument document= getDocument();
603 // final String category= "__template_position_importer" +
604 // System.currentTimeMillis(); //$NON-NLS-1$
605 // IPositionUpdater updater= new DefaultPositionUpdater(category);
606 // document.addPositionCategory(category);
607 // document.addPositionUpdater(updater);
608 // document.addPosition(position);
610 // CodeGenerationSettings settings=
611 // JavaPreferencesSettings.getCodeGenerationSettings();
612 // ImportsStructure structure= new ImportsStructure(cu,
613 // settings.importOrder, settings.importThreshold, true);
614 // structure.addImport("java.util.Iterator"); //$NON-NLS-1$
615 // structure.create(false, null);
617 // document.removePosition(position);
618 // document.removePositionUpdater(updater);
619 // document.removePositionCategory(category);
621 // setCompletionOffset(position.getOffset());
622 // setCompletionLength(position.getLength());
624 // } catch (CoreException e) {
625 // handleException(null, e);
626 // } catch (BadLocationException e) {
627 // handleException(null, e);
628 // } catch (BadPositionCategoryException e) {
629 // handleException(null, e);
633 * Evaluates a 'java' template in thecontext of a compilation unit
635 public static String evaluateTemplate(Template template,
636 ICompilationUnit compilationUnit, int position)
637 throws CoreException, BadLocationException, TemplateException {
639 TemplateContextType contextType = WebUI.getDefault()
640 .getTemplateContextRegistry().getContextType("java"); //$NON-NLS-1$
641 if (contextType == null)
642 throw new CoreException(
645 PHPeclipsePlugin.PLUGIN_ID,
648 .getString("JavaContext.error.message"), null)); //$NON-NLS-1$
650 IDocument document = new Document();
651 if (compilationUnit != null && compilationUnit.exists())
652 document.set(compilationUnit.getSource());
654 JavaContext context = new JavaContext(contextType, document, position,
656 context.setForceEvaluation(true);
658 TemplateBuffer buffer = context.evaluate(template);
661 return buffer.getString();