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.io.IOException;
14 import java.util.ArrayList;
15 import java.util.Arrays;
16 import java.util.HashMap;
17 import java.util.HashSet;
18 import java.util.Iterator;
19 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.IType;
27 import net.sourceforge.phpdt.core.JavaCore;
28 import net.sourceforge.phpdt.core.ToolFactory;
29 import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
30 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
31 import net.sourceforge.phpdt.internal.compiler.DefaultErrorHandlingPolicies;
32 import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
33 import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
34 import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
35 import net.sourceforge.phpdt.internal.compiler.parser.SyntaxError;
36 import net.sourceforge.phpdt.internal.compiler.parser.UnitParser;
37 import net.sourceforge.phpdt.internal.compiler.parser.VariableInfo;
38 import net.sourceforge.phpdt.internal.compiler.problem.DefaultProblemFactory;
39 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
40 import net.sourceforge.phpdt.internal.corext.template.php.JavaContext;
41 import net.sourceforge.phpdt.internal.corext.template.php.JavaContextType;
42 import net.sourceforge.phpdt.internal.ui.text.PHPCodeReader;
43 import net.sourceforge.phpdt.internal.ui.text.java.IPHPCompletionProposal;
44 import net.sourceforge.phpdt.internal.ui.text.java.JavaParameterListValidator;
45 import net.sourceforge.phpdt.internal.ui.text.java.PHPCompletionProposalComparator;
46 import net.sourceforge.phpdt.internal.ui.text.template.BuiltInEngine;
47 import net.sourceforge.phpdt.internal.ui.text.template.DeclarationEngine;
48 import net.sourceforge.phpdt.internal.ui.text.template.LocalVariableProposal;
49 import net.sourceforge.phpdt.internal.ui.text.template.contentassist.TemplateEngine;
50 import net.sourceforge.phpdt.ui.IWorkingCopyManager;
51 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
52 import net.sourceforge.phpeclipse.builder.IdentifierIndexManager;
53 import net.sourceforge.phpeclipse.phpeditor.PHPEditor;
54 import net.sourceforge.phpeclipse.phpeditor.PHPSyntaxRdr;
55 import net.sourceforge.phpeclipse.ui.WebUI;
57 import org.eclipse.core.resources.IFile;
58 import org.eclipse.core.resources.IProject;
59 import org.eclipse.jface.text.BadLocationException;
60 import org.eclipse.jface.text.IDocument;
61 import org.eclipse.jface.text.IRegion;
62 import org.eclipse.jface.text.ITextViewer;
63 import org.eclipse.jface.text.Region;
64 import org.eclipse.jface.text.contentassist.ICompletionProposal;
65 import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
66 import org.eclipse.jface.text.contentassist.IContextInformation;
67 import org.eclipse.jface.text.contentassist.IContextInformationExtension;
68 import org.eclipse.jface.text.contentassist.IContextInformationValidator;
69 import org.eclipse.jface.text.templates.TemplateContextType;
70 import org.eclipse.swt.graphics.Image;
71 import org.eclipse.swt.graphics.Point;
72 import org.eclipse.ui.IEditorInput;
73 import org.eclipse.ui.IEditorPart;
74 import org.eclipse.ui.IFileEditorInput;
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
82 * characters around its popup location.
84 // protected static class Validator implements IContextInformationValidator,
85 // IContextInformationPresenter {
86 // protected int fInstallOffset;
89 // * @see IContextInformationValidator#isContextInformationValid(int)
91 // public boolean isContextInformationValid(int offset) {
92 // return Math.abs(fInstallOffset - offset) < 5;
96 // * @see IContextInformationValidator#install(IContextInformation,
99 // public void install(IContextInformation info, ITextViewer viewer, int
101 // fInstallOffset = offset;
106 // org.eclipse.jface.text.contentassist.IContextInformationPresenter#updatePresentation(int,
109 // public boolean updatePresentation(int documentPosition, TextPresentation
114 private static class ContextInformationWrapper implements
115 IContextInformation, IContextInformationExtension {
116 private final IContextInformation fContextInformation;
118 private int fPosition;
120 public ContextInformationWrapper(IContextInformation contextInformation) {
121 fContextInformation = contextInformation;
125 * @see IContextInformation#getContextDisplayString()
127 public String getContextDisplayString() {
128 return fContextInformation.getContextDisplayString();
132 * @see IContextInformation#getImage()
134 public Image getImage() {
135 return fContextInformation.getImage();
139 * @see IContextInformation#getInformationDisplayString()
141 public String getInformationDisplayString() {
142 return fContextInformation.getInformationDisplayString();
146 * @see IContextInformationExtension#getContextInformationPosition()
148 public int getContextInformationPosition() {
152 public void setContextInformationPosition(int position) {
153 fPosition = position;
157 // private class TableName {
158 // String fTableName;
161 // fTableName = null;
165 // * @return Returns the tableName.
167 // public String getTableName() {
168 // if (fTableName == null) {
169 // return "<!--no-table-->";
171 // return fTableName;
175 // * @param tableName
176 // * The tableName to set.
178 // public void setTableName(String tableName) {
179 // fTableName = tableName;
183 private char[] fProposalAutoActivationSet;
185 protected IContextInformationValidator fValidator = null;
187 private TemplateEngine fTemplateEngine;
189 private PHPCompletionProposalComparator fComparator;
191 private IEditorPart fEditor;
193 protected IWorkingCopyManager fManager;
195 public PHPCompletionProcessor(IEditorPart editor) {
197 fManager = WebUI.getDefault().getWorkingCopyManager();
198 TemplateContextType contextType = WebUI.getDefault()
199 .getTemplateContextRegistry().getContextType("php"); //$NON-NLS-1$
200 if (contextType != null)
201 fTemplateEngine = new TemplateEngine(contextType);
202 fComparator = new PHPCompletionProposalComparator();
206 * Tells this processor to order the proposals alphabetically.
209 * <code>true</code> if proposals should be ordered.
211 public void orderProposalsAlphabetically(boolean order) {
212 fComparator.setOrderAlphabetically(order);
216 * Sets this processor's set of characters triggering the activation of the
217 * completion proposal computation.
219 * @param activationSet
222 public void setCompletionProposalAutoActivationCharacters(
223 char[] activationSet) {
224 fProposalAutoActivationSet = activationSet;
228 * (non-Javadoc) Method declared on IContentAssistProcessor
230 public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer,
231 int documentOffset) {
232 int contextInformationPosition = guessContextInformationPosition(
233 viewer, documentOffset);
234 return internalComputeCompletionProposals(viewer, documentOffset,
235 contextInformationPosition);
238 private int getLastToken(List list, ITextViewer viewer,
239 int completionPosition, JavaContext context) {
240 // TableName tableName) {
241 IDocument document = viewer.getDocument();
242 int start = context.getStart();
243 // int end = context.getEnd();
245 int lastSignificantToken = ITerminalSymbols.TokenNameEOF;
247 // begin search 2 lines behind of this
252 ch = document.getChar(--j);
258 ch = document.getChar(--j);
265 // scan the line for the dereferencing operator '->'
266 startText = document.get(j, start - j);
268 System.out.println(startText);
270 int token = ITerminalSymbols.TokenNameEOF;
271 // token = getLastSQLToken(startText);
272 // tableName.setTableName(getLastSQLTableName(startText));
273 Scanner scanner = ToolFactory
274 .createScanner(false, false, false);
275 scanner.setSource(startText.toCharArray());
276 scanner.setPHPMode(true);
277 int beforeLastToken = ITerminalSymbols.TokenNameEOF;
278 int lastToken = ITerminalSymbols.TokenNameEOF;
281 token = scanner.getNextToken();
283 while (token != ITerminalSymbols.TokenNameERROR
284 && token != ITerminalSymbols.TokenNameEOF) {
285 beforeLastToken = lastToken;
286 if (token == ITerminalSymbols.TokenNameVariable) {
287 ident = scanner.getCurrentTokenSource();
288 if (ident.length == 5 && ident[0] == '$'
289 && ident[1] == 't' && ident[2] == 'h'
290 && ident[3] == 'i' && ident[4] == 's') {
291 token = ITerminalSymbols.TokenNamethis_PHP_COMPLETION;
295 // System.out.println(scanner.toStringAction(lastToken));
296 token = scanner.getNextToken();
298 } catch (InvalidInputException e1) {
299 } catch (SyntaxError e) {
302 case ITerminalSymbols.TokenNameMINUS_GREATER:
303 // dereferencing operator '->' found
304 lastSignificantToken = ITerminalSymbols.TokenNameMINUS_GREATER;
305 if (beforeLastToken == ITerminalSymbols.TokenNameVariable) {
306 lastSignificantToken = ITerminalSymbols.TokenNameVariable;
308 } else if (beforeLastToken == ITerminalSymbols.TokenNamethis_PHP_COMPLETION) {
309 lastSignificantToken = ITerminalSymbols.TokenNamethis_PHP_COMPLETION;
313 case ITerminalSymbols.TokenNamenew:
314 lastSignificantToken = ITerminalSymbols.TokenNamenew;
318 } catch (BadLocationException e) {
320 return lastSignificantToken;
323 String getSQLTableName(String sqlText, int start) {
324 int tableNameStart = -1;
325 int currentCharacterPosition = start + 1;
329 ch = sqlText.charAt(currentCharacterPosition++);
330 if (tableNameStart == -1 && Scanner.isPHPIdentifierStart(ch)) {
331 tableNameStart = currentCharacterPosition - 1;
333 if (!Scanner.isPHPIdentifierPart(ch)) {
334 return sqlText.substring(tableNameStart,
335 currentCharacterPosition - 1);
339 } catch (IndexOutOfBoundsException e) {
340 if (tableNameStart >= 0) {
341 return sqlText.substring(tableNameStart,
342 currentCharacterPosition - 1);
348 // private String getLastSQLTableName(String startText) {
349 // // scan for sql identifiers
351 // int currentSQLPosition = startText.length();
352 // int identEnd = -1;
353 // String ident = null;
356 // ch = startText.charAt(--currentSQLPosition);
357 // if (Scanner.isSQLIdentifierPart(ch)) {
358 // // if (ch >= 'A' && ch <= 'Z') {
359 // if (identEnd < 0) {
360 // identEnd = currentSQLPosition + 1;
362 // // } else if (ch >= 'a' && ch <= 'z') {
363 // // if (identEnd < 0) {
364 // // identEnd = currentSQLPosition + 1;
366 // } else if (identEnd >= 0) {
367 // ident = startText.substring(currentSQLPosition + 1, identEnd);
368 // // select -- from -- where --
369 // // update -- set -- where --
370 // // insert into -- ( -- ) values ( -- )
371 // if (ident.length() >= 4 && ident.length() <= 6) {
372 // ident = ident.toLowerCase();
373 // switch (ident.length()) {
375 // // if (ident.equals("set")) {
376 // // // System.out.println("set");
377 // // token = ITerminalSymbols.TokenNameSQLset;
382 // if (ident.equals("from")) {
383 // // System.out.println("from");
384 // return getSQLTableName(startText, identEnd);
385 // } else if (ident.equals("into")) {
386 // // System.out.println("into");
387 // return getSQLTableName(startText, identEnd);
391 // if (ident.equals("update")) {
392 // // System.out.println("update");
393 // return getSQLTableName(startText, identEnd);
399 // } else if (Character.isWhitespace(ch)) {
402 // } catch (IndexOutOfBoundsException e) {
404 // return "<!--no-table-->";
408 * Detect the last significant SQL token in the text before the completion
412 // private int getLastSQLToken(String startText) {
414 // // scan for sql identifiers
416 // int currentSQLPosition = startText.length();
417 // int identEnd = -1;
418 // String ident = null;
421 // ch = startText.charAt(--currentSQLPosition);
422 // if (ch >= 'A' && ch <= 'Z') {
423 // if (identEnd < 0) {
424 // identEnd = currentSQLPosition + 1;
426 // } else if (ch >= 'a' && ch <= 'z') {
427 // if (identEnd < 0) {
428 // identEnd = currentSQLPosition + 1;
430 // } else if (identEnd >= 0) {
431 // ident = startText.substring(currentSQLPosition + 1, identEnd);
432 // // select -- from -- where --
433 // // update -- set -- where --
434 // // insert into -- ( -- ) values ( -- )
435 // if (ident.length() >= 3 && ident.length() <= 6) {
436 // ident = ident.toLowerCase();
437 // switch (ident.length()) {
439 // if (ident.equals("set")) {
440 // // System.out.println("set");
441 // token = ITerminalSymbols.TokenNameSQLset;
446 // if (ident.equals("from")) {
447 // // System.out.println("from");
448 // token = ITerminalSymbols.TokenNameSQLfrom;
449 // // getSQLTableName();
451 // } else if (ident.equals("into")) {
452 // // System.out.println("into");
453 // token = ITerminalSymbols.TokenNameSQLinto;
458 // if (ident.equals("where")) {
459 // // System.out.println("where");
460 // token = ITerminalSymbols.TokenNameSQLwhere;
465 // if (ident.equals("select")) {
466 // // System.out.println("select");
467 // token = ITerminalSymbols.TokenNameSQLselect;
469 // } else if (ident.equals("insert")) {
470 // // System.out.println("insert");
471 // token = ITerminalSymbols.TokenNameSQLinsert;
473 // } else if (ident.equals("update")) {
474 // // System.out.println("update");
475 // token = ITerminalSymbols.TokenNameSQLupdate;
477 // } else if (ident.equals("values")) {
478 // // System.out.println("values");
479 // token = ITerminalSymbols.TokenNameSQLvalues;
488 // } catch (IndexOutOfBoundsException e) {
490 // return ITerminalSymbols.TokenNameEOF;
492 private ICompletionProposal[] internalComputeCompletionProposals(
493 ITextViewer viewer, int offset, int contextOffset) {
494 ICompilationUnit unit = fManager.getWorkingCopy(fEditor
496 IDocument document = viewer.getDocument();
498 IProject project = null;
500 PHPEditor editor = null;
501 if (fEditor != null && (fEditor instanceof PHPEditor)) {
502 editor = (PHPEditor) fEditor;
503 IEditorInput editorInput = editor.getEditorInput();
504 if (editorInput instanceof IFileEditorInput) {
505 file = ((IFileEditorInput) editorInput).getFile();
506 project = file.getProject();
508 return new ICompletionProposal[0];
513 Point selection = viewer.getSelectedRange();
514 // remember selected text
515 String selectedText = null;
516 if (selection.y != 0) {
518 selectedText = document.get(selection.x, selection.y);
519 } catch (BadLocationException e) {
523 if (offset > 2 && fProposalAutoActivationSet != null) {
524 // restrict auto activation for '>' character to '->' token
527 char ch = document.getChar(offset - 1);
529 for (int i = 0; i < fProposalAutoActivationSet.length; i++) {
530 ch = fProposalAutoActivationSet[i];
531 if (ch == '>') { // auto activation enabled
532 ch = document.getChar(offset - 2);
534 return new IPHPCompletionProposal[0];
540 } catch (BadLocationException e) {
545 JavaContextType phpContextType = (JavaContextType) WebUI
546 .getDefault().getTemplateContextRegistry()
547 .getContextType("php"); //$NON-NLS-1$
548 JavaContext context = (JavaContext) phpContextType.createContext(
549 document, offset, selection.y, unit);
550 context.setVariable("selection", selectedText); //$NON-NLS-1$
551 String prefix = context.getKey();
553 HashMap methodVariables = null;
554 // HashMap typeVariables = null;
555 HashMap unitVariables = null;
556 ICompilationUnit compilationUnit = (ICompilationUnit) context
557 .findEnclosingElement(IJavaElement.COMPILATION_UNIT);
558 // if (compilationUnit != null) {
559 // unitVariables = ((CompilationUnit) compilationUnit).variables;
561 IType type = (IType) context.findEnclosingElement(IJavaElement.TYPE);
563 // typeVariables = ((SourceType) type).variables;
565 IMethod method = (IMethod) context
566 .findEnclosingElement(IJavaElement.METHOD);
567 // if (method != null) {
568 // methodVariables = ((SourceMethod) method).variables;
571 boolean emptyPrefix = prefix == null || prefix.equals("");
572 IPHPCompletionProposal[] localVariableResults = new IPHPCompletionProposal[0];
574 if (!emptyPrefix && prefix.length() >= 1 && prefix.charAt(0) == '$') {
576 String lowerCasePrefix = prefix.toLowerCase();
577 HashSet localVariables = new HashSet();
578 if (compilationUnit != null) {
579 unitVariables = getUnitVariables(unitVariables, compilationUnit);
580 getVariableProposals(localVariables, viewer, project, context,
581 unitVariables, lowerCasePrefix, 94);
583 if (method != null) {
584 methodVariables = getMethodVariables(methodVariables, method);
585 getVariableProposals(localVariables, viewer, project, context,
586 methodVariables, lowerCasePrefix, 99);
588 if (!localVariables.isEmpty()) {
589 localVariableResults = (IPHPCompletionProposal[]) localVariables
590 .toArray(new IPHPCompletionProposal[localVariables
595 // TableName sqlTable = new TableName();
596 ArrayList list = new ArrayList();
598 int lastSignificantToken = getLastToken(list, viewer, offset, context); // ,
600 boolean useClassMembers = (lastSignificantToken == ITerminalSymbols.TokenNameMINUS_GREATER)
601 || (lastSignificantToken == ITerminalSymbols.TokenNameVariable)
602 || (lastSignificantToken == ITerminalSymbols.TokenNamenew)
603 || (lastSignificantToken == ITerminalSymbols.TokenNamethis_PHP_COMPLETION);
605 if (fTemplateEngine != null) {
606 IPHPCompletionProposal[] templateResults = new IPHPCompletionProposal[0];
607 ICompletionProposal[] results;
609 fTemplateEngine.reset();
610 fTemplateEngine.complete(viewer, offset, unit);
611 templateResults = fTemplateEngine.getResults();
614 IPHPCompletionProposal[] identifierResults = new IPHPCompletionProposal[0];
616 // declarations stored in file project.index on project level
617 IPHPCompletionProposal[] declarationResults = new IPHPCompletionProposal[0];
618 if (project != null) {
619 DeclarationEngine declarationEngine;
620 JavaContextType contextType = (JavaContextType) WebUI
621 .getDefault().getTemplateContextRegistry()
622 .getContextType("php"); //$NON-NLS-1$
623 if (contextType != null) {
624 IdentifierIndexManager indexManager = WebUI
625 .getDefault().getIndexManager(project);
627 declarationEngine = new DeclarationEngine(project,
628 contextType, lastSignificantToken, file);
629 if (lastSignificantToken == ITerminalSymbols.TokenNamethis_PHP_COMPLETION) {
630 // complete '$this->'
631 sortedMap = indexManager.getIdentifiers(file);
632 declarationEngine.completeObject(viewer, offset,
635 String typeRef = null;
636 char[] varName = (char[]) list.get(0);
637 if (varName != null) {
638 if (method != null) {
639 methodVariables = getMethodVariables(
640 methodVariables, method);
641 VariableInfo info = (VariableInfo) methodVariables
642 .get(new String(varName));
643 if (info != null && info.typeIdentifier != null) {
644 typeRef = new String(info.typeIdentifier);
648 if (typeRef != null) {
649 // complete '$variable->' with type information
650 sortedMap = indexManager.getIdentifiers(typeRef);
651 declarationEngine.completeObject(viewer, offset,
654 // complete '$variable->' without type information
655 sortedMap = indexManager.getIdentifierMap();
656 declarationEngine.complete(viewer, offset,
660 declarationResults = declarationEngine.getResults();
663 // built in function names from phpsyntax.xml
664 ArrayList syntaxbuffer = PHPSyntaxRdr.getSyntaxData();
665 IPHPCompletionProposal[] builtinResults = new IPHPCompletionProposal[0];
666 if ((!useClassMembers) && syntaxbuffer != null) {
667 BuiltInEngine builtinEngine;
668 JavaContextType contextType = (JavaContextType) WebUI
669 .getDefault().getTemplateContextRegistry()
670 .getContextType("php"); //$NON-NLS-1$
671 if (contextType != null) {
672 builtinEngine = new BuiltInEngine(contextType);
673 builtinEngine.complete(viewer, offset, syntaxbuffer, unit);
674 builtinResults = builtinEngine.getResults();
677 // ICompletionProposal[] sqlResults = new ICompletionProposal[0];
678 // if (project != null) {
679 // sqlResults = getSQLProposals(viewer, project, context, prefix,
682 // concatenate the result arrays
683 IPHPCompletionProposal[] total;
684 total = new IPHPCompletionProposal[localVariableResults.length
685 + templateResults.length + identifierResults.length
686 + builtinResults.length + declarationResults.length];// +
687 // sqlResults.length];
688 System.arraycopy(templateResults, 0, total, 0,
689 templateResults.length);
690 System.arraycopy(identifierResults, 0, total,
691 templateResults.length, identifierResults.length);
692 System.arraycopy(builtinResults, 0, total, templateResults.length
693 + identifierResults.length, builtinResults.length);
694 System.arraycopy(declarationResults, 0, total,
695 templateResults.length + identifierResults.length
696 + builtinResults.length, declarationResults.length);
697 // System.arraycopy(sqlResults, 0, total, templateResults.length +
698 // identifierResults.length + builtinResults.length
699 // + declarationResults.length, sqlResults.length);
700 // System.arraycopy(localVariableResults, 0, total,
701 // templateResults.length
702 // + identifierResults.length + builtinResults.length
703 // + declarationResults.length + sqlResults.length,
704 // localVariableResults.length);
706 .arraycopy(localVariableResults, 0, total,
707 templateResults.length + identifierResults.length
708 + builtinResults.length
709 + declarationResults.length,
710 localVariableResults.length);
712 // fNumberOfComputedResults = (results == null ? 0 :
715 * Order here and not in result collector to make sure that the
716 * order applies to all proposals and not just those of the
719 return order(results);
721 return new IPHPCompletionProposal[0];
725 * @param unitVariables
728 private HashMap getUnitVariables(HashMap unitVariables,
729 ICompilationUnit unit) {
730 if (unitVariables == null) {
732 String unitText = unit.getSource();
733 unitVariables = new HashMap();
735 ProblemReporter problemReporter = new ProblemReporter(
736 DefaultErrorHandlingPolicies.exitAfterAllProblems(),
737 new CompilerOptions(JavaCore.getOptions()),
738 new DefaultProblemFactory());
739 UnitParser parser = new UnitParser(problemReporter);
740 parser.compilationUnit = new CompilationUnitDeclaration(
741 problemReporter, null, unitText.length());
742 parser.parse(unitText, unitVariables);
744 } catch (Exception e) {
745 // TODO Auto-generated catch block
747 PHPeclipsePlugin.log(e);
750 return unitVariables;
754 * @param methodVariables
757 private HashMap getMethodVariables(HashMap methodVariables, IMethod method) {
758 if (methodVariables == null) {
760 String methodText = method.getSource();
761 methodVariables = new HashMap();
762 ProblemReporter problemReporter = new ProblemReporter(
763 DefaultErrorHandlingPolicies.exitAfterAllProblems(),
764 new CompilerOptions(JavaCore.getOptions()),
765 new DefaultProblemFactory());
766 UnitParser parser = new UnitParser(problemReporter);
767 parser.compilationUnit = new CompilationUnitDeclaration(
768 problemReporter, null, methodText.length());
769 parser.parseFunction(methodText, methodVariables);
770 } catch (Exception e) {
771 // TODO Auto-generated catch block
773 PHPeclipsePlugin.log(e);
776 return methodVariables;
786 private void getVariableProposals(HashSet localVariables,
787 ITextViewer viewer, IProject project, JavaContext context,
788 HashMap variables, String prefix, int relevance) {
790 int start = context.getStart();
791 int end = context.getEnd();
792 IRegion region = new Region(start, end - start);
793 // IMethod method = (IMethod)
794 // context.findEnclosingElement(IJavaElement.METHOD);
795 // if (method != null && (method instanceof SourceMethod) &&
797 // method).variables != null) {
798 // HashMap map = ((SourceMethod) method).variables;
799 Set set = variables.keySet();
800 Iterator iter = set.iterator();
802 boolean matchesVarName;
803 while (iter.hasNext()) {
804 varName = (String) iter.next();
805 if (varName.length() >= prefix.length()) {
806 matchesVarName = true;
807 for (int i = 0; i < prefix.length(); i++) {
808 if (prefix.charAt(i) != Character.toLowerCase(varName
810 matchesVarName = false;
814 if (matchesVarName) {
815 LocalVariableProposal prop;
816 // if (varName.length == prefix.length()) {
817 // prop = new LocalVariableProposal(new String(varName),
819 // viewer, relevance-10);
821 prop = new LocalVariableProposal(new String(varName),
822 region, viewer, relevance);
824 localVariables.add(prop);
831 // boolean matchesVarName;
832 // if (method != null) {
833 // ISourceRange range = method.getSourceRange();
834 // char[] source = method.getSource().toCharArray();
835 // Scanner scanner = new Scanner();
836 // scanner.setSource(source);
837 // scanner.phpMode = true;
838 // int token = Scanner.TokenNameWHITESPACE;
839 // while ((token = scanner.getNextToken()) != Scanner.TokenNameEOF) {
840 // if (token == Scanner.TokenNameVariable) {
841 // varName = scanner.getCurrentTokenSource();
842 // if (varName.length >= prefix.length()) {
843 // matchesVarName = true;
844 // for (int i = 0; i < prefix.length(); i++) {
845 // if (prefix.charAt(i) != varName[i]) {
846 // matchesVarName = false;
850 // if (matchesVarName) {
851 // LocalVariableProposal prop = new LocalVariableProposal(new
852 // String(varName), region, viewer);
853 // if (varName.length == prefix.length()) {
854 // prop.setRelevance(98);
856 // localVariables.add(prop);
862 // } catch (Throwable e) {
863 // // ignore - Syntax exceptions could occur, if there are syntax errors
877 // private ICompletionProposal[] getSQLProposals(ITextViewer viewer,
879 // project, DocumentTemplateContext context,
880 // String prefix, TableName sqlTable) {
881 // ICompletionProposal[] sqlResults = new ICompletionProposal[0];
882 // // Get The Database bookmark from the Quantum SQL plugin:
883 // // BookmarkCollection sqlBookMarks = BookmarkCollection.getInstance();
884 // // if (sqlBookMarks != null) {
885 // String bookmarkString =
886 // ProjectPrefUtil.getMiscProjectsPreferenceValue(project,
887 // IPreferenceConstants.PHP_BOOKMARK_DEFAULT);
888 // if (bookmarkString != null && !bookmarkString.equals("")) {
889 // String[] bookmarks = ExternalInterface.getBookmarkNames();
890 // boolean foundBookmark = false;
891 // for (int i = 0; i < bookmarks.length; i++) {
892 // if (bookmarks[i].equals(bookmarkString)) {
893 // foundBookmark = true;
896 // if (!foundBookmark) {
897 // return sqlResults;
899 // // Bookmark bookmark = sqlBookMarks.find(bookmarkString);
900 // ArrayList sqlList = new ArrayList();
901 // if (!ExternalInterface.isBookmarkConnected(bookmarkString)) {
902 // ExternalInterface.connectBookmark(bookmarkString, null);
903 // if (!ExternalInterface.isBookmarkConnected(bookmarkString)) {
904 // return sqlResults;
907 // // if (ExternalInterface.isBookmarkConnected(bookmarkString)) {
909 // int start = context.getStart();
910 // int end = context.getEnd();
911 // String foundSQLTableName = sqlTable.getTableName();
913 // String columnName;
914 // String prefixWithoutDollar = prefix;
915 // boolean isDollarPrefix = false;
916 // if (prefix.length() > 0 && prefix.charAt(0) == '$') {
917 // prefixWithoutDollar = prefix.substring(1);
918 // isDollarPrefix = true;
920 // IRegion region = new Region(start, end - start);
922 // if (!isDollarPrefix) {
923 // String[] tableNames = ExternalInterface.getMatchingTableNames(null,
924 // bookmarkString, prefixWithoutDollar, null, false);
925 // for (int i = 0; i < tableNames.length; i++) {
926 // sqlList.add(new SQLProposal(tableNames[i], context, region, viewer,
927 // PHPUiImages.get(PHPUiImages.IMG_TABLE)));
931 // String[] columnNames = ExternalInterface.getMatchingColumnNames(null,
932 // bookmarkString, prefixWithoutDollar, null, false);
933 // for (int i = 0; i < columnNames.length; i++) {
934 // sqlList.add(new SQLProposal(columnNames[i], context, region, viewer,
935 // PHPUiImages.get(PHPUiImages.IMG_TABLE)));
938 // sqlResults = new IPHPCompletionProposal[sqlList.size()];
939 // for (int i = 0; i < sqlList.size(); i++) {
940 // sqlResults[i] = (SQLProposal) sqlList.get(i);
942 // } catch (Exception /* NotConnectedException */ e) {
948 // return sqlResults;
950 private boolean looksLikeMethod(PHPCodeReader reader) throws IOException {
951 int curr = reader.read();
952 while (curr != PHPCodeReader.EOF && Character.isWhitespace((char) curr))
953 curr = reader.read();
955 if (curr == PHPCodeReader.EOF)
958 return Scanner.isPHPIdentifierPart((char) curr);
961 private int guessContextInformationPosition(ITextViewer viewer, int offset) {
962 int contextPosition = offset;
963 IDocument document = viewer.getDocument();
966 PHPCodeReader reader = new PHPCodeReader();
967 reader.configureBackwardReader(document, offset, true, true);
969 int nestingLevel = 0;
971 int curr = reader.read();
972 while (curr != PHPCodeReader.EOF) {
974 if (')' == (char) curr)
977 else if ('(' == (char) curr) {
980 if (nestingLevel < 0) {
981 int start = reader.getOffset();
982 if (looksLikeMethod(reader))
987 curr = reader.read();
989 } catch (IOException e) {
991 return contextPosition;
995 * @see IContentAssistProcessor#computeContextInformation(ITextViewer, int)
997 public IContextInformation[] computeContextInformation(ITextViewer viewer,
999 int contextInformationPosition = guessContextInformationPosition(
1001 List result = addContextInformations(viewer, contextInformationPosition);
1002 return (IContextInformation[]) result
1003 .toArray(new IContextInformation[result.size()]);
1006 private List addContextInformations(ITextViewer viewer, int offset) {
1007 ICompletionProposal[] proposals = internalComputeCompletionProposals(
1008 viewer, offset, -1);
1009 List result = new ArrayList();
1010 for (int i = 0; i < proposals.length; i++) {
1011 IContextInformation contextInformation = proposals[i]
1012 .getContextInformation();
1013 if (contextInformation != null) {
1014 ContextInformationWrapper wrapper = new ContextInformationWrapper(
1015 contextInformation);
1016 wrapper.setContextInformationPosition(offset);
1017 result.add(wrapper);
1024 * Order the given proposals.
1026 private ICompletionProposal[] order(ICompletionProposal[] proposals) {
1027 Arrays.sort(proposals, fComparator);
1028 // int len = proposals.length;
1032 // for (int i = 0; i < len; i++) {
1033 // System.out.println(proposals[i].getDisplayString());
1039 * (non-Javadoc) Method declared on IContentAssistProcessor
1041 public char[] getCompletionProposalAutoActivationCharacters() {
1042 return fProposalAutoActivationSet;
1043 // return null; // new char[] { '$' };
1047 * (non-Javadoc) Method declared on IContentAssistProcessor
1049 public char[] getContextInformationAutoActivationCharacters() {
1054 * (non-Javadoc) Method declared on IContentAssistProcessor
1056 public IContextInformationValidator getContextInformationValidator() {
1057 if (fValidator == null)
1058 fValidator = new JavaParameterListValidator();
1063 * (non-Javadoc) Method declared on IContentAssistProcessor
1065 public String getErrorMessage() {