1 /**********************************************************************
 
   2  Copyright (c) 2000, 2002 IBM Corp. 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 implementation
 
  10  **********************************************************************/
 
  11 package net.sourceforge.phpeclipse.phpeditor.php;
 
  13 import java.sql.Connection;
 
  14 import java.sql.DatabaseMetaData;
 
  15 import java.sql.ResultSet;
 
  16 import java.sql.SQLException;
 
  17 import java.util.ArrayList;
 
  18 import java.util.Arrays;
 
  19 import java.util.HashSet;
 
  20 import java.util.List;
 
  21 import java.util.SortedMap;
 
  23 import net.sourceforge.phpdt.core.ICompilationUnit;
 
  24 import net.sourceforge.phpdt.core.IJavaElement;
 
  25 import net.sourceforge.phpdt.core.IMethod;
 
  26 import net.sourceforge.phpdt.core.ISourceRange;
 
  27 import net.sourceforge.phpdt.core.ToolFactory;
 
  28 import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
 
  29 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
 
  30 import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
 
  31 import net.sourceforge.phpdt.internal.corext.template.php.JavaContext;
 
  32 import net.sourceforge.phpdt.internal.corext.template.php.JavaContextType;
 
  33 import net.sourceforge.phpdt.internal.ui.PHPUiImages;
 
  34 import net.sourceforge.phpdt.internal.ui.text.java.IPHPCompletionProposal;
 
  35 import net.sourceforge.phpdt.internal.ui.text.java.PHPCompletionProposalComparator;
 
  36 import net.sourceforge.phpdt.internal.ui.text.template.BuiltInEngine;
 
  37 import net.sourceforge.phpdt.internal.ui.text.template.DeclarationEngine;
 
  38 import net.sourceforge.phpdt.internal.ui.text.template.IdentifierEngine;
 
  39 import net.sourceforge.phpdt.internal.ui.text.template.LocalVariableProposal;
 
  40 import net.sourceforge.phpdt.internal.ui.text.template.SQLProposal;
 
  41 import net.sourceforge.phpdt.internal.ui.text.template.contentassist.TemplateEngine;
 
  42 import net.sourceforge.phpdt.ui.IWorkingCopyManager;
 
  43 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
 
  44 import net.sourceforge.phpeclipse.builder.IdentifierIndexManager;
 
  45 import net.sourceforge.phpeclipse.phpeditor.PHPEditor;
 
  46 import net.sourceforge.phpeclipse.phpeditor.PHPSyntaxRdr;
 
  47 import net.sourceforge.phpeclipse.ui.IPreferenceConstants;
 
  48 import net.sourceforge.phpeclipse.ui.overlaypages.ProjectPrefUtil;
 
  50 import org.eclipse.core.resources.IFile;
 
  51 import org.eclipse.core.resources.IProject;
 
  52 import org.eclipse.jface.text.BadLocationException;
 
  53 import org.eclipse.jface.text.IDocument;
 
  54 import org.eclipse.jface.text.IRegion;
 
  55 import org.eclipse.jface.text.ITextViewer;
 
  56 import org.eclipse.jface.text.Region;
 
  57 import org.eclipse.jface.text.TextPresentation;
 
  58 import org.eclipse.jface.text.contentassist.ICompletionProposal;
 
  59 import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
 
  60 import org.eclipse.jface.text.contentassist.IContextInformation;
 
  61 import org.eclipse.jface.text.contentassist.IContextInformationExtension;
 
  62 import org.eclipse.jface.text.contentassist.IContextInformationPresenter;
 
  63 import org.eclipse.jface.text.contentassist.IContextInformationValidator;
 
  64 import org.eclipse.jface.text.templates.DocumentTemplateContext;
 
  65 import org.eclipse.jface.text.templates.TemplateContextType;
 
  66 import org.eclipse.swt.graphics.Image;
 
  67 import org.eclipse.swt.graphics.Point;
 
  68 import org.eclipse.ui.IEditorPart;
 
  69 import org.eclipse.ui.IFileEditorInput;
 
  71 import com.quantum.model.Bookmark;
 
  72 import com.quantum.model.BookmarkCollection;
 
  73 import com.quantum.model.NotConnectedException;
 
  74 import com.quantum.util.connection.ConnectionUtil;
 
  77  * Example PHP completion processor.
 
  79 public class PHPCompletionProcessor implements IContentAssistProcessor {
 
  81    * Simple content assist tip closer. The tip is valid in a range of 5 characters around its popup location.
 
  83   protected static class Validator implements IContextInformationValidator, IContextInformationPresenter {
 
  84     protected int fInstallOffset;
 
  87      * @see IContextInformationValidator#isContextInformationValid(int)
 
  89     public boolean isContextInformationValid(int offset) {
 
  90       return Math.abs(fInstallOffset - offset) < 5;
 
  94      * @see IContextInformationValidator#install(IContextInformation, ITextViewer, int)
 
  96     public void install(IContextInformation info, ITextViewer viewer, int offset) {
 
  97       fInstallOffset = offset;
 
 101      * @see org.eclipse.jface.text.contentassist.IContextInformationPresenter#updatePresentation(int, TextPresentation)
 
 103     public boolean updatePresentation(int documentPosition, TextPresentation presentation) {
 
 108   private static class ContextInformationWrapper implements IContextInformation, IContextInformationExtension {
 
 109     private final IContextInformation fContextInformation;
 
 111     private int fPosition;
 
 113     public ContextInformationWrapper(IContextInformation contextInformation) {
 
 114       fContextInformation = contextInformation;
 
 118      * @see IContextInformation#getContextDisplayString()
 
 120     public String getContextDisplayString() {
 
 121       return fContextInformation.getContextDisplayString();
 
 125      * @see IContextInformation#getImage()
 
 127     public Image getImage() {
 
 128       return fContextInformation.getImage();
 
 132      * @see IContextInformation#getInformationDisplayString()
 
 134     public String getInformationDisplayString() {
 
 135       return fContextInformation.getInformationDisplayString();
 
 139      * @see IContextInformationExtension#getContextInformationPosition()
 
 141     public int getContextInformationPosition() {
 
 145     public void setContextInformationPosition(int position) {
 
 146       fPosition = position;
 
 150   private class TableName {
 
 158      * @return Returns the tableName.
 
 160     public String getTableName() {
 
 161       if (fTableName == null) {
 
 162         return "<!--no-table-->";
 
 169      *          The tableName to set.
 
 171     public void setTableName(String tableName) {
 
 172       fTableName = tableName;
 
 176   private char[] fProposalAutoActivationSet;
 
 178   protected IContextInformationValidator fValidator = new Validator();
 
 180   private TemplateEngine fTemplateEngine;
 
 182   private PHPCompletionProposalComparator fComparator;
 
 184   private int fNumberOfComputedResults = 0;
 
 186   private IEditorPart fEditor;
 
 188   protected IWorkingCopyManager fManager;
 
 190   public PHPCompletionProcessor(IEditorPart editor) {
 
 192     fManager = PHPeclipsePlugin.getDefault().getWorkingCopyManager();
 
 193     TemplateContextType contextType = PHPeclipsePlugin.getDefault().getTemplateContextRegistry().getContextType("php"); //$NON-NLS-1$
 
 194     if (contextType != null)
 
 195       fTemplateEngine = new TemplateEngine(contextType);
 
 196     fComparator = new PHPCompletionProposalComparator();
 
 200    * Tells this processor to order the proposals alphabetically.
 
 203    *          <code>true</code> if proposals should be ordered.
 
 205   public void orderProposalsAlphabetically(boolean order) {
 
 206     fComparator.setOrderAlphabetically(order);
 
 210    * Sets this processor's set of characters triggering the activation of the completion proposal computation.
 
 212    * @param activationSet
 
 215   public void setCompletionProposalAutoActivationCharacters(char[] activationSet) {
 
 216     fProposalAutoActivationSet = activationSet;
 
 220    * (non-Javadoc) Method declared on IContentAssistProcessor
 
 222   public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int documentOffset) {
 
 223     int contextInformationPosition = guessContextInformationPosition(viewer, documentOffset);
 
 224     return internalComputeCompletionProposals(viewer, documentOffset, contextInformationPosition);
 
 227   private int getLastToken(ITextViewer viewer, int completionPosition, JavaContext context, TableName tableName) {
 
 228     IDocument document = viewer.getDocument();
 
 229     int start = context.getStart();
 
 230     int end = context.getEnd();
 
 232     int lastSignificantToken = ITerminalSymbols.TokenNameEOF;
 
 234       // begin search 2 lines behind of this
 
 239           ch = document.getChar(j);
 
 245           ch = document.getChar(j);
 
 252         // scan the line for the dereferencing operator '->'
 
 253         startText = document.get(j, start - j);
 
 255           System.out.println(startText);
 
 257         int token = ITerminalSymbols.TokenNameEOF;
 
 258         //        token = getLastSQLToken(startText);
 
 259         tableName.setTableName(getLastSQLTableName(startText));
 
 260         Scanner scanner = ToolFactory.createScanner(false, false, false);
 
 261         scanner.setSource(startText.toCharArray());
 
 262         scanner.setPHPMode(true);
 
 263         int beforeLastToken = ITerminalSymbols.TokenNameEOF;
 
 264         int lastToken = ITerminalSymbols.TokenNameEOF;
 
 267           token = scanner.getNextToken();
 
 269           while (token != ITerminalSymbols.TokenNameERROR && token != ITerminalSymbols.TokenNameEOF) {
 
 270             beforeLastToken = lastToken;
 
 271             if (lastToken == ITerminalSymbols.TokenNameVariable) {
 
 272               ident = scanner.getCurrentTokenSource();
 
 273               if (ident.length == 5 && ident[0] == '$' && ident[1] == 't' && ident[2] == 'h' && ident[3] == 'i' && ident[4] == 's') {
 
 274                 beforeLastToken = ITerminalSymbols.TokenNamethis_PHP_COMPLETION;
 
 278             //                                                          System.out.println(scanner.toStringAction(lastToken));
 
 279             token = scanner.getNextToken();
 
 281         } catch (InvalidInputException e1) {
 
 284         case ITerminalSymbols.TokenNameMINUS_GREATER:
 
 285           // dereferencing operator '->' found
 
 286           lastSignificantToken = ITerminalSymbols.TokenNameMINUS_GREATER;
 
 287           if (beforeLastToken == ITerminalSymbols.TokenNameVariable) {
 
 288             lastSignificantToken = ITerminalSymbols.TokenNameVariable;
 
 291         case ITerminalSymbols.TokenNamenew:
 
 292           lastSignificantToken = ITerminalSymbols.TokenNamenew;
 
 296     } catch (BadLocationException e) {
 
 298     return lastSignificantToken;
 
 301   String getSQLTableName(String sqlText, int start) {
 
 302     int tableNameStart = -1;
 
 303     int currentCharacterPosition = start + 1;
 
 307         ch = sqlText.charAt(currentCharacterPosition++);
 
 308         if (tableNameStart == -1 && Character.isJavaIdentifierStart(ch)) {
 
 309           tableNameStart = currentCharacterPosition - 1;
 
 311           if (!Character.isJavaIdentifierPart(ch)) {
 
 312             return sqlText.substring(tableNameStart, currentCharacterPosition - 1);
 
 316     } catch (IndexOutOfBoundsException e) {
 
 317       if (tableNameStart >= 0) {
 
 318         return sqlText.substring(tableNameStart, currentCharacterPosition - 1);
 
 324   private String getLastSQLTableName(String startText) {
 
 326     // scan for sql identifiers
 
 328     int currentSQLPosition = startText.length();
 
 331     boolean whiteSpace = true;
 
 334         ch = startText.charAt(--currentSQLPosition);
 
 335         if (ch >= 'A' && ch <= 'Z') {
 
 337             identEnd = currentSQLPosition + 1;
 
 339         } else if (ch >= 'a' && ch <= 'z') {
 
 341             identEnd = currentSQLPosition + 1;
 
 343         } else if (identEnd >= 0) {
 
 344           ident = startText.substring(currentSQLPosition + 1, identEnd);
 
 345           // select -- from -- where --
 
 346           // update -- set -- where --
 
 347           // insert into -- ( -- ) values ( -- )
 
 348           if (ident.length() >= 4 && ident.length() <= 6) {
 
 349             ident = ident.toLowerCase();
 
 350             switch (ident.length()) {
 
 352             //                if (ident.equals("set")) {
 
 353             //                  // System.out.println("set");
 
 354             //                  token = ITerminalSymbols.TokenNameSQLset;
 
 359               if (ident.equals("from")) {
 
 360                 //                  System.out.println("from");
 
 361                 token = ITerminalSymbols.TokenNameSQLfrom;
 
 362                 return getSQLTableName(startText, identEnd);
 
 363               } else if (ident.equals("into")) {
 
 364                 //                System.out.println("into");
 
 365                 token = ITerminalSymbols.TokenNameSQLinto;
 
 366                 return getSQLTableName(startText, identEnd);
 
 370             //                if (ident.equals("where")) {
 
 371             //                  // System.out.println("where");
 
 372             //                  token = ITerminalSymbols.TokenNameSQLwhere;
 
 377               //                if (ident.equals("select")) {
 
 378               //                  // System.out.println("select");
 
 379               //                  token = ITerminalSymbols.TokenNameSQLselect;
 
 381               //                } else if (ident.equals("insert")) {
 
 382               //                  // System.out.println("insert");
 
 383               //                  token = ITerminalSymbols.TokenNameSQLinsert;
 
 386               if (ident.equals("update")) {
 
 387                 //                  System.out.println("update");
 
 388                 token = ITerminalSymbols.TokenNameSQLupdate;
 
 389                 return getSQLTableName(startText, identEnd);
 
 391               //                else if (ident.equals("values")) {
 
 392               //                  // System.out.println("values");
 
 393               //                  token = ITerminalSymbols.TokenNameSQLvalues;
 
 401         } else if (Character.isWhitespace(ch)) {
 
 406     } catch (IndexOutOfBoundsException e) {
 
 408     return "<!--no-table-->";
 
 412    * Detect the last significant SQL token in the text before the completion
 
 416   private int getLastSQLToken(String startText) {
 
 418     // scan for sql identifiers
 
 420     int currentSQLPosition = startText.length();
 
 423     boolean whiteSpace = true;
 
 426         ch = startText.charAt(--currentSQLPosition);
 
 427         if (ch >= 'A' && ch <= 'Z') {
 
 429             identEnd = currentSQLPosition + 1;
 
 431         } else if (ch >= 'a' && ch <= 'z') {
 
 433             identEnd = currentSQLPosition + 1;
 
 435         } else if (identEnd >= 0) {
 
 436           ident = startText.substring(currentSQLPosition + 1, identEnd);
 
 437           // select -- from -- where --
 
 438           // update -- set -- where --
 
 439           // insert into -- ( -- ) values ( -- )
 
 440           if (ident.length() >= 3 && ident.length() <= 6) {
 
 441             ident = ident.toLowerCase();
 
 442             switch (ident.length()) {
 
 444               if (ident.equals("set")) {
 
 445                 //                  System.out.println("set");
 
 446                 token = ITerminalSymbols.TokenNameSQLset;
 
 451               if (ident.equals("from")) {
 
 452                 //                  System.out.println("from");
 
 453                 token = ITerminalSymbols.TokenNameSQLfrom;
 
 456               } else if (ident.equals("into")) {
 
 457                 //                System.out.println("into");
 
 458                 token = ITerminalSymbols.TokenNameSQLinto;
 
 463               if (ident.equals("where")) {
 
 464                 //                  System.out.println("where");
 
 465                 token = ITerminalSymbols.TokenNameSQLwhere;
 
 470               if (ident.equals("select")) {
 
 471                 //                  System.out.println("select");
 
 472                 token = ITerminalSymbols.TokenNameSQLselect;
 
 474               } else if (ident.equals("insert")) {
 
 475                 //                  System.out.println("insert");
 
 476                 token = ITerminalSymbols.TokenNameSQLinsert;
 
 478               } else if (ident.equals("update")) {
 
 479                 //                  System.out.println("update");
 
 480                 token = ITerminalSymbols.TokenNameSQLupdate;
 
 482               } else if (ident.equals("values")) {
 
 483                 //                System.out.println("values");
 
 484                 token = ITerminalSymbols.TokenNameSQLvalues;
 
 492         } else if (Character.isWhitespace(ch)) {
 
 497     } catch (IndexOutOfBoundsException e) {
 
 499     return ITerminalSymbols.TokenNameEOF;
 
 502   private ICompletionProposal[] internalComputeCompletionProposals(ITextViewer viewer, int offset, int contextOffset) {
 
 503     ICompilationUnit unit = fManager.getWorkingCopy(fEditor.getEditorInput());
 
 504     IDocument document = viewer.getDocument();
 
 505     Object[] identifiers = null;
 
 507     IProject project = null;
 
 509       PHPEditor editor = null;
 
 510       if (fEditor != null && (fEditor instanceof PHPEditor)) {
 
 511         editor = (PHPEditor) fEditor;
 
 512         file = ((IFileEditorInput) editor.getEditorInput()).getFile();
 
 513         project = file.getProject();
 
 517     Point selection = viewer.getSelectedRange();
 
 519     // remember selected text
 
 520     String selectedText = null;
 
 521     if (selection.y != 0) {
 
 523         selectedText = document.get(selection.x, selection.y);
 
 524       } catch (BadLocationException e) {
 
 528     JavaContextType phpContextType = (JavaContextType) PHPeclipsePlugin.getDefault().getTemplateContextRegistry().getContextType(
 
 529         "php"); //$NON-NLS-1$
 
 530     JavaContext context = (JavaContext) phpContextType.createContext(document, offset, selection.y, unit);
 
 531     context.setVariable("selection", selectedText); //$NON-NLS-1$
 
 532     String prefix = context.getKey();
 
 533     boolean emptyPrefix = prefix == null || prefix.equals("");
 
 534     IPHPCompletionProposal[] localVariableResults = new IPHPCompletionProposal[0];
 
 535     if (!emptyPrefix && prefix.length() >= 1 && prefix.charAt(0) == '$') { // php Variable ?
 
 536       HashSet localVariables = getLocalVariableProposals(viewer, project, context, prefix);
 
 537       if (localVariables.size() > 0) {
 
 538         localVariableResults = (IPHPCompletionProposal[]) localVariables.toArray(new IPHPCompletionProposal[localVariables.size()]);
 
 542     TableName sqlTable = new TableName();
 
 543     int lastSignificantToken = getLastToken(viewer, offset, context, sqlTable);
 
 544     boolean useClassMembers = (lastSignificantToken == ITerminalSymbols.TokenNameMINUS_GREATER)
 
 545         || (lastSignificantToken == ITerminalSymbols.TokenNameVariable) || (lastSignificantToken == ITerminalSymbols.TokenNamenew)
 
 546         || (lastSignificantToken == ITerminalSymbols.TokenNamethis_PHP_COMPLETION);
 
 548     if (fTemplateEngine != null) {
 
 549       IPHPCompletionProposal[] templateResults = new IPHPCompletionProposal[0];
 
 550       ICompletionProposal[] results;
 
 552         fTemplateEngine.reset();
 
 553         fTemplateEngine.complete(viewer, offset, unit);
 
 554         templateResults = fTemplateEngine.getResults();
 
 556       IPHPCompletionProposal[] identifierResults = new IPHPCompletionProposal[0];
 
 557       if ((!useClassMembers) && identifiers != null) {
 
 558         IdentifierEngine identifierEngine;
 
 559         JavaContextType contextType = (JavaContextType) PHPeclipsePlugin.getDefault().getTemplateContextRegistry().getContextType(
 
 560             "php"); //$NON-NLS-1$
 
 561         if (contextType != null) {
 
 562           identifierEngine = new IdentifierEngine(contextType);
 
 563           identifierEngine.complete(viewer, offset, identifiers, unit);
 
 564           identifierResults = identifierEngine.getResults();
 
 567       // declarations stored in file project.index on project level
 
 568       IPHPCompletionProposal[] declarationResults = new IPHPCompletionProposal[0];
 
 569       if (project != null) {
 
 570         DeclarationEngine declarationEngine;
 
 571         JavaContextType contextType = (JavaContextType) PHPeclipsePlugin.getDefault().getTemplateContextRegistry().getContextType(
 
 572             "php"); //$NON-NLS-1$
 
 573         if (contextType != null) {
 
 574           IdentifierIndexManager indexManager = PHPeclipsePlugin.getDefault().getIndexManager(project);
 
 575           SortedMap sortedMap = indexManager.getIdentifierMap();
 
 576           declarationEngine = new DeclarationEngine(project, contextType, lastSignificantToken, file);
 
 577           declarationEngine.complete(viewer, offset, sortedMap, unit);
 
 578           declarationResults = declarationEngine.getResults();
 
 581       // built in function names from phpsyntax.xml
 
 582       ArrayList syntaxbuffer = PHPSyntaxRdr.getSyntaxData();
 
 583       IPHPCompletionProposal[] builtinResults = new IPHPCompletionProposal[0];
 
 584       if ((!useClassMembers) && syntaxbuffer != null) {
 
 585         BuiltInEngine builtinEngine;
 
 587         JavaContextType contextType = (JavaContextType) PHPeclipsePlugin.getDefault().getTemplateContextRegistry().getContextType(
 
 588             "php"); //$NON-NLS-1$
 
 589         if (contextType != null) {
 
 590           builtinEngine = new BuiltInEngine(contextType);
 
 591           builtinEngine.complete(viewer, offset, syntaxbuffer, unit);
 
 592           builtinResults = builtinEngine.getResults();
 
 595       ICompletionProposal[] sqlResults = new ICompletionProposal[0];
 
 596       if (project != null) {
 
 597         sqlResults = getSQLProposals(viewer, project, context, prefix, sqlTable);
 
 599       // concatenate the result arrays
 
 600       IPHPCompletionProposal[] total;
 
 601       total = new IPHPCompletionProposal[localVariableResults.length + templateResults.length + identifierResults.length
 
 602           + builtinResults.length + declarationResults.length + sqlResults.length];
 
 603       System.arraycopy(templateResults, 0, total, 0, templateResults.length);
 
 604       System.arraycopy(identifierResults, 0, total, templateResults.length, identifierResults.length);
 
 605       System.arraycopy(builtinResults, 0, total, templateResults.length + identifierResults.length, builtinResults.length);
 
 606       System.arraycopy(declarationResults, 0, total, templateResults.length + identifierResults.length + builtinResults.length,
 
 607           declarationResults.length);
 
 608       System.arraycopy(sqlResults, 0, total, templateResults.length + identifierResults.length + builtinResults.length
 
 609           + declarationResults.length, sqlResults.length);
 
 610       System.arraycopy(localVariableResults, 0, total, templateResults.length + identifierResults.length + builtinResults.length
 
 611           + declarationResults.length + sqlResults.length, localVariableResults.length);
 
 613       fNumberOfComputedResults = (results == null ? 0 : results.length);
 
 615        * Order here and not in result collector to make sure that the order applies to all proposals and not just those of the
 
 618       return order(results);
 
 620     return new IPHPCompletionProposal[0];
 
 630   private HashSet getLocalVariableProposals(ITextViewer viewer, IProject project, JavaContext context, String prefix) {
 
 631     HashSet localVariables = new HashSet();
 
 633       IMethod method = (IMethod) context.findEnclosingElement(IJavaElement.METHOD);
 
 634       int start = context.getStart();
 
 635       int end = context.getEnd();
 
 636       IRegion region = new Region(start, end - start);
 
 638       boolean matchesVarName;
 
 639       if (method != null) {
 
 640         ISourceRange range = method.getSourceRange();
 
 641         char[] source = method.getSource().toCharArray();
 
 642         Scanner scanner = new Scanner();
 
 643         scanner.setSource(source);
 
 644         scanner.phpMode = true;
 
 645         int token = Scanner.TokenNameWHITESPACE;
 
 646         while ((token = scanner.getNextToken()) != Scanner.TokenNameEOF) {
 
 647           if (token == Scanner.TokenNameVariable) {
 
 648             varName = scanner.getCurrentTokenSource();
 
 649             if (varName.length >= prefix.length()) {
 
 650               matchesVarName = true;
 
 651               for (int i = 0; i < prefix.length(); i++) {
 
 652                 if (prefix.charAt(i) != varName[i]) {
 
 653                   matchesVarName = false;
 
 657               if (matchesVarName) {
 
 658                 LocalVariableProposal prop = new LocalVariableProposal(new String(varName), region, viewer);
 
 659                 if (varName.length == prefix.length()) {
 
 660                   prop.setRelevance(98);
 
 662                 localVariables.add(prop);
 
 668     } catch (Throwable e) {
 
 669       // ignore - Syntax exceptions could occur, if there are syntax errors !
 
 671     return localVariables;
 
 683   private ICompletionProposal[] getSQLProposals(ITextViewer viewer, IProject project, DocumentTemplateContext context,
 
 684       String prefix, TableName sqlTable) {
 
 685     ICompletionProposal[] sqlResults = new ICompletionProposal[0];
 
 686     // Get The Database bookmark from the Quantum SQL plugin:
 
 687     BookmarkCollection sqlBookMarks = BookmarkCollection.getInstance();
 
 688     if (sqlBookMarks != null) {
 
 689       String bookmarkString = ProjectPrefUtil.getMiscProjectsPreferenceValue(project, IPreferenceConstants.PHP_BOOKMARK_DEFAULT);
 
 690       if (bookmarkString != null && !bookmarkString.equals("")) {
 
 691         Bookmark bookmark = sqlBookMarks.find(bookmarkString);
 
 692         ArrayList sqlList = new ArrayList();
 
 693         if (bookmark != null && !bookmark.isConnected()) {
 
 694           new ConnectionUtil().connect(bookmark, null);
 
 696         if (bookmark != null && bookmark.isConnected()) {
 
 698             Connection connection = bookmark.getConnection();
 
 699             DatabaseMetaData metaData = connection.getMetaData();
 
 701             if (metaData != null) {
 
 702               int start = context.getStart();
 
 703               int end = context.getEnd();
 
 704               String foundSQLTableName = sqlTable.getTableName();
 
 707               String prefixWithoutDollar = prefix;
 
 708               boolean isDollarPrefix = false;
 
 709               if (prefix.length() > 0 && prefix.charAt(0) == '$') {
 
 710                 prefixWithoutDollar = prefix.substring(1);
 
 711                 isDollarPrefix = true;
 
 713               IRegion region = new Region(start, end - start);
 
 715               if (!isDollarPrefix) {
 
 716                 set = metaData.getTables(null, null, prefixWithoutDollar + "%", null);
 
 718                   //                  String tempSchema = set.getString("TABLE_SCHEM");
 
 719                   //                  tempSchema = (tempSchema == null) ? "" :
 
 720                   // tempSchema.trim();
 
 721                   tableName = set.getString("TABLE_NAME");
 
 722                   tableName = (tableName == null) ? "" : tableName.trim();
 
 723                   if (tableName != null && tableName.length() > 0) {
 
 724                     sqlList.add(new SQLProposal(tableName, context, region, viewer, PHPUiImages.get(PHPUiImages.IMG_TABLE)));
 
 729               set = metaData.getColumns(null, null, "%", prefixWithoutDollar + "%");
 
 730               SQLProposal sqlProposal;
 
 732                 columnName = set.getString("COLUMN_NAME");
 
 733                 columnName = (columnName == null) ? "" : columnName.trim();
 
 734                 tableName = set.getString("TABLE_NAME");
 
 735                 tableName = (tableName == null) ? "" : tableName.trim();
 
 736                 if (tableName != null && tableName.length() > 0 && columnName != null && columnName.length() > 0) {
 
 737                   if (isDollarPrefix) {
 
 738                     sqlProposal = new SQLProposal(tableName, "$" + columnName, context, region, viewer, PHPUiImages
 
 739                         .get(PHPUiImages.IMG_COLUMN));
 
 741                     sqlProposal = new SQLProposal(tableName, columnName, context, region, viewer, PHPUiImages
 
 742                         .get(PHPUiImages.IMG_COLUMN));
 
 744                   if (tableName.equals(foundSQLTableName)) {
 
 745                     sqlProposal.setRelevance(90);
 
 746                   } else if (tableName.indexOf(foundSQLTableName) >= 0) {
 
 747                     sqlProposal.setRelevance(75);
 
 749                   sqlList.add(sqlProposal);
 
 753               sqlResults = new IPHPCompletionProposal[sqlList.size()];
 
 754               for (int i = 0; i < sqlList.size(); i++) {
 
 755                 sqlResults[i] = (SQLProposal) sqlList.get(i);
 
 758           } catch (NotConnectedException e) {
 
 759             // ignore this - not mission critical
 
 760           } catch (SQLException e) {
 
 769   private int guessContextInformationPosition(ITextViewer viewer, int offset) {
 
 770     int contextPosition = offset;
 
 771     IDocument document = viewer.getDocument();
 
 774     //      PHPCodeReader reader= new PHPCodeReader();
 
 775     //      reader.configureBackwardReader(document, offset, true, true);
 
 777     //      int nestingLevel= 0;
 
 779     //      int curr= reader.read();
 
 780     //      while (curr != PHPCodeReader.EOF) {
 
 782     //        if (')' == (char) curr)
 
 785     //        else if ('(' == (char) curr) {
 
 788     //          if (nestingLevel < 0) {
 
 789     //            int start= reader.getOffset();
 
 790     //            if (looksLikeMethod(reader))
 
 795     //        curr= reader.read();
 
 797     //    } catch (IOException e) {
 
 799     return contextPosition;
 
 803    * @see IContentAssistProcessor#computeContextInformation(ITextViewer, int)
 
 805   public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) {
 
 806     int contextInformationPosition = guessContextInformationPosition(viewer, offset);
 
 807     List result = addContextInformations(viewer, contextInformationPosition);
 
 808     return (IContextInformation[]) result.toArray(new IContextInformation[result.size()]);
 
 811   private List addContextInformations(ITextViewer viewer, int offset) {
 
 812     ICompletionProposal[] proposals = internalComputeCompletionProposals(viewer, offset, -1);
 
 813     List result = new ArrayList();
 
 814     for (int i = 0; i < proposals.length; i++) {
 
 815       IContextInformation contextInformation = proposals[i].getContextInformation();
 
 816       if (contextInformation != null) {
 
 817         ContextInformationWrapper wrapper = new ContextInformationWrapper(contextInformation);
 
 818         wrapper.setContextInformationPosition(offset);
 
 826    * Order the given proposals.
 
 828   private ICompletionProposal[] order(ICompletionProposal[] proposals) {
 
 829     Arrays.sort(proposals, fComparator);
 
 834    * (non-Javadoc) Method declared on IContentAssistProcessor
 
 836   public char[] getCompletionProposalAutoActivationCharacters() {
 
 837     return fProposalAutoActivationSet;
 
 838     //    return null; // new char[] { '$' };
 
 842    * (non-Javadoc) Method declared on IContentAssistProcessor
 
 844   public char[] getContextInformationAutoActivationCharacters() {
 
 845     return new char[] {};
 
 849    * (non-Javadoc) Method declared on IContentAssistProcessor
 
 851   public IContextInformationValidator getContextInformationValidator() {
 
 856    * (non-Javadoc) Method declared on IContentAssistProcessor
 
 858   public String getErrorMessage() {