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();