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;
56 import org.eclipse.core.resources.IFile;
57 import org.eclipse.core.resources.IProject;
58 import org.eclipse.jface.text.BadLocationException;
59 import org.eclipse.jface.text.IDocument;
60 import org.eclipse.jface.text.IRegion;
61 import org.eclipse.jface.text.ITextViewer;
62 import org.eclipse.jface.text.Region;
63 import org.eclipse.jface.text.contentassist.ICompletionProposal;
64 import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
65 import org.eclipse.jface.text.contentassist.IContextInformation;
66 import org.eclipse.jface.text.contentassist.IContextInformationExtension;
67 import org.eclipse.jface.text.contentassist.IContextInformationValidator;
68 import org.eclipse.jface.text.templates.TemplateContextType;
69 import org.eclipse.swt.graphics.Image;
70 import org.eclipse.swt.graphics.Point;
71 import org.eclipse.ui.IEditorInput;
72 import org.eclipse.ui.IEditorPart;
73 import org.eclipse.ui.IFileEditorInput;
76 * Example PHP completion processor.
78 public class PHPCompletionProcessor implements IContentAssistProcessor {
80 * Simple content assist tip closer. The tip is valid in a range of 5
81 * characters around its popup location.
83 // protected static class Validator implements IContextInformationValidator,
84 // IContextInformationPresenter {
85 // protected int fInstallOffset;
88 // * @see IContextInformationValidator#isContextInformationValid(int)
90 // public boolean isContextInformationValid(int offset) {
91 // return Math.abs(fInstallOffset - offset) < 5;
95 // * @see IContextInformationValidator#install(IContextInformation,
98 // public void install(IContextInformation info, ITextViewer viewer, int
100 // fInstallOffset = offset;
105 // org.eclipse.jface.text.contentassist.IContextInformationPresenter#updatePresentation(int,
108 // public boolean updatePresentation(int documentPosition, TextPresentation
113 private static class ContextInformationWrapper implements
114 IContextInformation, IContextInformationExtension {
115 private final IContextInformation fContextInformation;
117 private int fPosition;
119 public ContextInformationWrapper(IContextInformation contextInformation) {
120 fContextInformation = contextInformation;
124 * @see IContextInformation#getContextDisplayString()
126 public String getContextDisplayString() {
127 return fContextInformation.getContextDisplayString();
131 * @see IContextInformation#getImage()
133 public Image getImage() {
134 return fContextInformation.getImage();
138 * @see IContextInformation#getInformationDisplayString()
140 public String getInformationDisplayString() {
141 return fContextInformation.getInformationDisplayString();
145 * @see IContextInformationExtension#getContextInformationPosition()
147 public int getContextInformationPosition() {
151 public void setContextInformationPosition(int position) {
152 fPosition = position;
156 // private class TableName {
157 // String fTableName;
160 // fTableName = null;
164 // * @return Returns the tableName.
166 // public String getTableName() {
167 // if (fTableName == null) {
168 // return "<!--no-table-->";
170 // return fTableName;
174 // * @param tableName
175 // * The tableName to set.
177 // public void setTableName(String tableName) {
178 // fTableName = tableName;
182 private char[] fProposalAutoActivationSet;
184 protected IContextInformationValidator fValidator = null;
186 private TemplateEngine fTemplateEngine;
188 private PHPCompletionProposalComparator fComparator;
190 private IEditorPart fEditor;
192 protected IWorkingCopyManager fManager;
194 public PHPCompletionProcessor(IEditorPart editor) {
196 fManager = PHPeclipsePlugin.getDefault().getWorkingCopyManager();
197 TemplateContextType contextType = PHPeclipsePlugin.getDefault()
198 .getTemplateContextRegistry().getContextType("php"); //$NON-NLS-1$
199 if (contextType != null)
200 fTemplateEngine = new TemplateEngine(contextType);
201 fComparator = new PHPCompletionProposalComparator();
205 * Tells this processor to order the proposals alphabetically.
208 * <code>true</code> if proposals should be ordered.
210 public void orderProposalsAlphabetically(boolean order) {
211 fComparator.setOrderAlphabetically(order);
215 * Sets this processor's set of characters triggering the activation of the
216 * completion proposal computation.
218 * @param activationSet
221 public void setCompletionProposalAutoActivationCharacters(
222 char[] activationSet) {
223 fProposalAutoActivationSet = activationSet;
227 * (non-Javadoc) Method declared on IContentAssistProcessor
229 public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer,
230 int documentOffset) {
231 int contextInformationPosition = guessContextInformationPosition(
232 viewer, documentOffset);
233 return internalComputeCompletionProposals(viewer, documentOffset,
234 contextInformationPosition);
237 private int getLastToken(List list, ITextViewer viewer,
238 int completionPosition, JavaContext context) {
239 // TableName tableName) {
240 IDocument document = viewer.getDocument();
241 int start = context.getStart();
242 // int end = context.getEnd();
244 int lastSignificantToken = ITerminalSymbols.TokenNameEOF;
246 // begin search 2 lines behind of this
251 ch = document.getChar(j);
257 ch = document.getChar(j);
264 // scan the line for the dereferencing operator '->'
265 startText = document.get(j, start - j);
267 System.out.println(startText);
269 int token = ITerminalSymbols.TokenNameEOF;
270 // token = getLastSQLToken(startText);
271 // tableName.setTableName(getLastSQLTableName(startText));
272 Scanner scanner = ToolFactory
273 .createScanner(false, false, false);
274 scanner.setSource(startText.toCharArray());
275 scanner.setPHPMode(true);
276 int beforeLastToken = ITerminalSymbols.TokenNameEOF;
277 int lastToken = ITerminalSymbols.TokenNameEOF;
280 token = scanner.getNextToken();
282 while (token != ITerminalSymbols.TokenNameERROR
283 && token != ITerminalSymbols.TokenNameEOF) {
284 beforeLastToken = lastToken;
285 if (token == ITerminalSymbols.TokenNameVariable) {
286 ident = scanner.getCurrentTokenSource();
287 if (ident.length == 5 && ident[0] == '$'
288 && ident[1] == 't' && ident[2] == 'h'
289 && ident[3] == 'i' && ident[4] == 's') {
290 token = ITerminalSymbols.TokenNamethis_PHP_COMPLETION;
294 // System.out.println(scanner.toStringAction(lastToken));
295 token = scanner.getNextToken();
297 } catch (InvalidInputException e1) {
298 } catch (SyntaxError e) {
301 case ITerminalSymbols.TokenNameMINUS_GREATER:
302 // dereferencing operator '->' found
303 lastSignificantToken = ITerminalSymbols.TokenNameMINUS_GREATER;
304 if (beforeLastToken == ITerminalSymbols.TokenNameVariable) {
305 lastSignificantToken = ITerminalSymbols.TokenNameVariable;
307 } else if (beforeLastToken == ITerminalSymbols.TokenNamethis_PHP_COMPLETION) {
308 lastSignificantToken = ITerminalSymbols.TokenNamethis_PHP_COMPLETION;
312 case ITerminalSymbols.TokenNamenew:
313 lastSignificantToken = ITerminalSymbols.TokenNamenew;
317 } catch (BadLocationException e) {
319 return lastSignificantToken;
322 String getSQLTableName(String sqlText, int start) {
323 int tableNameStart = -1;
324 int currentCharacterPosition = start + 1;
328 ch = sqlText.charAt(currentCharacterPosition++);
329 if (tableNameStart == -1 && Scanner.isPHPIdentifierStart(ch)) {
330 tableNameStart = currentCharacterPosition - 1;
332 if (!Scanner.isPHPIdentifierPart(ch)) {
333 return sqlText.substring(tableNameStart,
334 currentCharacterPosition - 1);
338 } catch (IndexOutOfBoundsException e) {
339 if (tableNameStart >= 0) {
340 return sqlText.substring(tableNameStart,
341 currentCharacterPosition - 1);
347 // private String getLastSQLTableName(String startText) {
348 // // scan for sql identifiers
350 // int currentSQLPosition = startText.length();
351 // int identEnd = -1;
352 // String ident = null;
355 // ch = startText.charAt(--currentSQLPosition);
356 // if (Scanner.isSQLIdentifierPart(ch)) {
357 // // if (ch >= 'A' && ch <= 'Z') {
358 // if (identEnd < 0) {
359 // identEnd = currentSQLPosition + 1;
361 // // } else if (ch >= 'a' && ch <= 'z') {
362 // // if (identEnd < 0) {
363 // // identEnd = currentSQLPosition + 1;
365 // } else if (identEnd >= 0) {
366 // ident = startText.substring(currentSQLPosition + 1, identEnd);
367 // // select -- from -- where --
368 // // update -- set -- where --
369 // // insert into -- ( -- ) values ( -- )
370 // if (ident.length() >= 4 && ident.length() <= 6) {
371 // ident = ident.toLowerCase();
372 // switch (ident.length()) {
374 // // if (ident.equals("set")) {
375 // // // System.out.println("set");
376 // // token = ITerminalSymbols.TokenNameSQLset;
381 // if (ident.equals("from")) {
382 // // System.out.println("from");
383 // return getSQLTableName(startText, identEnd);
384 // } else if (ident.equals("into")) {
385 // // System.out.println("into");
386 // return getSQLTableName(startText, identEnd);
390 // if (ident.equals("update")) {
391 // // System.out.println("update");
392 // return getSQLTableName(startText, identEnd);
398 // } else if (Character.isWhitespace(ch)) {
401 // } catch (IndexOutOfBoundsException e) {
403 // return "<!--no-table-->";
407 * Detect the last significant SQL token in the text before the completion
411 // private int getLastSQLToken(String startText) {
413 // // scan for sql identifiers
415 // int currentSQLPosition = startText.length();
416 // int identEnd = -1;
417 // String ident = null;
420 // ch = startText.charAt(--currentSQLPosition);
421 // if (ch >= 'A' && ch <= 'Z') {
422 // if (identEnd < 0) {
423 // identEnd = currentSQLPosition + 1;
425 // } else if (ch >= 'a' && ch <= 'z') {
426 // if (identEnd < 0) {
427 // identEnd = currentSQLPosition + 1;
429 // } else if (identEnd >= 0) {
430 // ident = startText.substring(currentSQLPosition + 1, identEnd);
431 // // select -- from -- where --
432 // // update -- set -- where --
433 // // insert into -- ( -- ) values ( -- )
434 // if (ident.length() >= 3 && ident.length() <= 6) {
435 // ident = ident.toLowerCase();
436 // switch (ident.length()) {
438 // if (ident.equals("set")) {
439 // // System.out.println("set");
440 // token = ITerminalSymbols.TokenNameSQLset;
445 // if (ident.equals("from")) {
446 // // System.out.println("from");
447 // token = ITerminalSymbols.TokenNameSQLfrom;
448 // // getSQLTableName();
450 // } else if (ident.equals("into")) {
451 // // System.out.println("into");
452 // token = ITerminalSymbols.TokenNameSQLinto;
457 // if (ident.equals("where")) {
458 // // System.out.println("where");
459 // token = ITerminalSymbols.TokenNameSQLwhere;
464 // if (ident.equals("select")) {
465 // // System.out.println("select");
466 // token = ITerminalSymbols.TokenNameSQLselect;
468 // } else if (ident.equals("insert")) {
469 // // System.out.println("insert");
470 // token = ITerminalSymbols.TokenNameSQLinsert;
472 // } else if (ident.equals("update")) {
473 // // System.out.println("update");
474 // token = ITerminalSymbols.TokenNameSQLupdate;
476 // } else if (ident.equals("values")) {
477 // // System.out.println("values");
478 // token = ITerminalSymbols.TokenNameSQLvalues;
487 // } catch (IndexOutOfBoundsException e) {
489 // return ITerminalSymbols.TokenNameEOF;
491 private ICompletionProposal[] internalComputeCompletionProposals(
492 ITextViewer viewer, int offset, int contextOffset) {
493 ICompilationUnit unit = fManager.getWorkingCopy(fEditor
495 IDocument document = viewer.getDocument();
497 IProject project = null;
499 PHPEditor editor = null;
500 if (fEditor != null && (fEditor instanceof PHPEditor)) {
501 editor = (PHPEditor) fEditor;
502 IEditorInput editorInput = editor.getEditorInput();
503 if (editorInput instanceof IFileEditorInput) {
504 file = ((IFileEditorInput) editorInput).getFile();
505 project = file.getProject();
507 return new ICompletionProposal[0];
512 Point selection = viewer.getSelectedRange();
513 // remember selected text
514 String selectedText = null;
515 if (selection.y != 0) {
517 selectedText = document.get(selection.x, selection.y);
518 } catch (BadLocationException e) {
522 if (offset > 2 && fProposalAutoActivationSet != null) {
523 // restrict auto activation for '>' character to '->' token
526 char ch = document.getChar(offset - 1);
528 for (int i = 0; i < fProposalAutoActivationSet.length; i++) {
529 ch = fProposalAutoActivationSet[i];
530 if (ch == '>') { // auto activation enabled
531 ch = document.getChar(offset - 2);
533 return new IPHPCompletionProposal[0];
539 } catch (BadLocationException e) {
544 JavaContextType phpContextType = (JavaContextType) PHPeclipsePlugin
545 .getDefault().getTemplateContextRegistry()
546 .getContextType("php"); //$NON-NLS-1$
547 JavaContext context = (JavaContext) phpContextType.createContext(
548 document, offset, selection.y, unit);
549 context.setVariable("selection", selectedText); //$NON-NLS-1$
550 String prefix = context.getKey();
552 HashMap methodVariables = null;
553 // HashMap typeVariables = null;
554 HashMap unitVariables = null;
555 ICompilationUnit compilationUnit = (ICompilationUnit) context
556 .findEnclosingElement(IJavaElement.COMPILATION_UNIT);
557 // if (compilationUnit != null) {
558 // unitVariables = ((CompilationUnit) compilationUnit).variables;
560 IType type = (IType) context.findEnclosingElement(IJavaElement.TYPE);
562 // typeVariables = ((SourceType) type).variables;
564 IMethod method = (IMethod) context
565 .findEnclosingElement(IJavaElement.METHOD);
566 // if (method != null) {
567 // methodVariables = ((SourceMethod) method).variables;
570 boolean emptyPrefix = prefix == null || prefix.equals("");
571 IPHPCompletionProposal[] localVariableResults = new IPHPCompletionProposal[0];
573 if (!emptyPrefix && prefix.length() >= 1 && prefix.charAt(0) == '$') {
575 String lowerCasePrefix = prefix.toLowerCase();
576 HashSet localVariables = new HashSet();
577 if (compilationUnit != null) {
578 unitVariables = getUnitVariables(unitVariables, compilationUnit);
579 getVariableProposals(localVariables, viewer, project, context,
580 unitVariables, lowerCasePrefix, 94);
582 if (method != null) {
583 methodVariables = getMethodVariables(methodVariables, method);
584 getVariableProposals(localVariables, viewer, project, context,
585 methodVariables, lowerCasePrefix, 99);
587 if (!localVariables.isEmpty()) {
588 localVariableResults = (IPHPCompletionProposal[]) localVariables
589 .toArray(new IPHPCompletionProposal[localVariables
594 // TableName sqlTable = new TableName();
595 ArrayList list = new ArrayList();
597 int lastSignificantToken = getLastToken(list, viewer, offset, context); // ,
599 boolean useClassMembers = (lastSignificantToken == ITerminalSymbols.TokenNameMINUS_GREATER)
600 || (lastSignificantToken == ITerminalSymbols.TokenNameVariable)
601 || (lastSignificantToken == ITerminalSymbols.TokenNamenew)
602 || (lastSignificantToken == ITerminalSymbols.TokenNamethis_PHP_COMPLETION);
604 if (fTemplateEngine != null) {
605 IPHPCompletionProposal[] templateResults = new IPHPCompletionProposal[0];
606 ICompletionProposal[] results;
608 fTemplateEngine.reset();
609 fTemplateEngine.complete(viewer, offset, unit);
610 templateResults = fTemplateEngine.getResults();
613 IPHPCompletionProposal[] identifierResults = new IPHPCompletionProposal[0];
615 // declarations stored in file project.index on project level
616 IPHPCompletionProposal[] declarationResults = new IPHPCompletionProposal[0];
617 if (project != null) {
618 DeclarationEngine declarationEngine;
619 JavaContextType contextType = (JavaContextType) PHPeclipsePlugin
620 .getDefault().getTemplateContextRegistry()
621 .getContextType("php"); //$NON-NLS-1$
622 if (contextType != null) {
623 IdentifierIndexManager indexManager = PHPeclipsePlugin
624 .getDefault().getIndexManager(project);
626 declarationEngine = new DeclarationEngine(project,
627 contextType, lastSignificantToken, file);
628 if (lastSignificantToken == ITerminalSymbols.TokenNamethis_PHP_COMPLETION) {
629 // complete '$this->'
630 sortedMap = indexManager.getIdentifiers(file);
631 declarationEngine.completeObject(viewer, offset,
634 String typeRef = null;
635 char[] varName = (char[]) list.get(0);
636 if (varName != null) {
637 if (method != null) {
638 methodVariables = getMethodVariables(
639 methodVariables, method);
640 VariableInfo info = (VariableInfo) methodVariables
641 .get(new String(varName));
642 if (info != null && info.typeIdentifier != null) {
643 typeRef = new String(info.typeIdentifier);
647 if (typeRef != null) {
648 // complete '$variable->' with type information
649 sortedMap = indexManager.getIdentifiers(typeRef);
650 declarationEngine.completeObject(viewer, offset,
653 // complete '$variable->' without type information
654 sortedMap = indexManager.getIdentifierMap();
655 declarationEngine.complete(viewer, offset,
659 declarationResults = declarationEngine.getResults();
662 // built in function names from phpsyntax.xml
663 ArrayList syntaxbuffer = PHPSyntaxRdr.getSyntaxData();
664 IPHPCompletionProposal[] builtinResults = new IPHPCompletionProposal[0];
665 if ((!useClassMembers) && syntaxbuffer != null) {
666 BuiltInEngine builtinEngine;
667 JavaContextType contextType = (JavaContextType) PHPeclipsePlugin
668 .getDefault().getTemplateContextRegistry()
669 .getContextType("php"); //$NON-NLS-1$
670 if (contextType != null) {
671 builtinEngine = new BuiltInEngine(contextType);
672 builtinEngine.complete(viewer, offset, syntaxbuffer, unit);
673 builtinResults = builtinEngine.getResults();
676 // ICompletionProposal[] sqlResults = new ICompletionProposal[0];
677 // if (project != null) {
678 // sqlResults = getSQLProposals(viewer, project, context, prefix,
681 // concatenate the result arrays
682 IPHPCompletionProposal[] total;
683 total = new IPHPCompletionProposal[localVariableResults.length
684 + templateResults.length + identifierResults.length
685 + builtinResults.length + declarationResults.length];// +
686 // sqlResults.length];
687 System.arraycopy(templateResults, 0, total, 0,
688 templateResults.length);
689 System.arraycopy(identifierResults, 0, total,
690 templateResults.length, identifierResults.length);
691 System.arraycopy(builtinResults, 0, total, templateResults.length
692 + identifierResults.length, builtinResults.length);
693 System.arraycopy(declarationResults, 0, total,
694 templateResults.length + identifierResults.length
695 + builtinResults.length, declarationResults.length);
696 // System.arraycopy(sqlResults, 0, total, templateResults.length +
697 // identifierResults.length + builtinResults.length
698 // + declarationResults.length, sqlResults.length);
699 // System.arraycopy(localVariableResults, 0, total,
700 // templateResults.length
701 // + identifierResults.length + builtinResults.length
702 // + declarationResults.length + sqlResults.length,
703 // localVariableResults.length);
705 .arraycopy(localVariableResults, 0, total,
706 templateResults.length + identifierResults.length
707 + builtinResults.length
708 + declarationResults.length,
709 localVariableResults.length);
711 // fNumberOfComputedResults = (results == null ? 0 :
714 * Order here and not in result collector to make sure that the
715 * order applies to all proposals and not just those of the
718 return order(results);
720 return new IPHPCompletionProposal[0];
724 * @param unitVariables
727 private HashMap getUnitVariables(HashMap unitVariables,
728 ICompilationUnit unit) {
729 if (unitVariables == null) {
731 String unitText = unit.getSource();
732 unitVariables = new HashMap();
734 ProblemReporter problemReporter = new ProblemReporter(
735 DefaultErrorHandlingPolicies.exitAfterAllProblems(),
736 new CompilerOptions(JavaCore.getOptions()),
737 new DefaultProblemFactory());
738 UnitParser parser = new UnitParser(problemReporter);
739 parser.compilationUnit = new CompilationUnitDeclaration(
740 problemReporter, null, unitText.length());
741 parser.parse(unitText, unitVariables);
743 } catch (Exception e) {
744 // TODO Auto-generated catch block
746 PHPeclipsePlugin.log(e);
749 return unitVariables;
753 * @param methodVariables
756 private HashMap getMethodVariables(HashMap methodVariables, IMethod method) {
757 if (methodVariables == null) {
759 String methodText = method.getSource();
760 methodVariables = new HashMap();
761 ProblemReporter problemReporter = new ProblemReporter(
762 DefaultErrorHandlingPolicies.exitAfterAllProblems(),
763 new CompilerOptions(JavaCore.getOptions()),
764 new DefaultProblemFactory());
765 UnitParser parser = new UnitParser(problemReporter);
766 parser.compilationUnit = new CompilationUnitDeclaration(
767 problemReporter, null, methodText.length());
768 parser.parseFunction(methodText, methodVariables);
769 } catch (Exception e) {
770 // TODO Auto-generated catch block
772 PHPeclipsePlugin.log(e);
775 return methodVariables;
785 private void getVariableProposals(HashSet localVariables,
786 ITextViewer viewer, IProject project, JavaContext context,
787 HashMap variables, String prefix, int relevance) {
789 int start = context.getStart();
790 int end = context.getEnd();
791 IRegion region = new Region(start, end - start);
792 // IMethod method = (IMethod)
793 // context.findEnclosingElement(IJavaElement.METHOD);
794 // if (method != null && (method instanceof SourceMethod) &&
796 // method).variables != null) {
797 // HashMap map = ((SourceMethod) method).variables;
798 Set set = variables.keySet();
799 Iterator iter = set.iterator();
801 boolean matchesVarName;
802 while (iter.hasNext()) {
803 varName = (String) iter.next();
804 if (varName.length() >= prefix.length()) {
805 matchesVarName = true;
806 for (int i = 0; i < prefix.length(); i++) {
807 if (prefix.charAt(i) != Character.toLowerCase(varName
809 matchesVarName = false;
813 if (matchesVarName) {
814 LocalVariableProposal prop;
815 // if (varName.length == prefix.length()) {
816 // prop = new LocalVariableProposal(new String(varName),
818 // viewer, relevance-10);
820 prop = new LocalVariableProposal(new String(varName),
821 region, viewer, relevance);
823 localVariables.add(prop);
830 // boolean matchesVarName;
831 // if (method != null) {
832 // ISourceRange range = method.getSourceRange();
833 // char[] source = method.getSource().toCharArray();
834 // Scanner scanner = new Scanner();
835 // scanner.setSource(source);
836 // scanner.phpMode = true;
837 // int token = Scanner.TokenNameWHITESPACE;
838 // while ((token = scanner.getNextToken()) != Scanner.TokenNameEOF) {
839 // if (token == Scanner.TokenNameVariable) {
840 // varName = scanner.getCurrentTokenSource();
841 // if (varName.length >= prefix.length()) {
842 // matchesVarName = true;
843 // for (int i = 0; i < prefix.length(); i++) {
844 // if (prefix.charAt(i) != varName[i]) {
845 // matchesVarName = false;
849 // if (matchesVarName) {
850 // LocalVariableProposal prop = new LocalVariableProposal(new
851 // String(varName), region, viewer);
852 // if (varName.length == prefix.length()) {
853 // prop.setRelevance(98);
855 // localVariables.add(prop);
861 // } catch (Throwable e) {
862 // // ignore - Syntax exceptions could occur, if there are syntax errors
876 // private ICompletionProposal[] getSQLProposals(ITextViewer viewer,
878 // project, DocumentTemplateContext context,
879 // String prefix, TableName sqlTable) {
880 // ICompletionProposal[] sqlResults = new ICompletionProposal[0];
881 // // Get The Database bookmark from the Quantum SQL plugin:
882 // // BookmarkCollection sqlBookMarks = BookmarkCollection.getInstance();
883 // // if (sqlBookMarks != null) {
884 // String bookmarkString =
885 // ProjectPrefUtil.getMiscProjectsPreferenceValue(project,
886 // IPreferenceConstants.PHP_BOOKMARK_DEFAULT);
887 // if (bookmarkString != null && !bookmarkString.equals("")) {
888 // String[] bookmarks = ExternalInterface.getBookmarkNames();
889 // boolean foundBookmark = false;
890 // for (int i = 0; i < bookmarks.length; i++) {
891 // if (bookmarks[i].equals(bookmarkString)) {
892 // foundBookmark = true;
895 // if (!foundBookmark) {
896 // return sqlResults;
898 // // Bookmark bookmark = sqlBookMarks.find(bookmarkString);
899 // ArrayList sqlList = new ArrayList();
900 // if (!ExternalInterface.isBookmarkConnected(bookmarkString)) {
901 // ExternalInterface.connectBookmark(bookmarkString, null);
902 // if (!ExternalInterface.isBookmarkConnected(bookmarkString)) {
903 // return sqlResults;
906 // // if (ExternalInterface.isBookmarkConnected(bookmarkString)) {
908 // int start = context.getStart();
909 // int end = context.getEnd();
910 // String foundSQLTableName = sqlTable.getTableName();
912 // String columnName;
913 // String prefixWithoutDollar = prefix;
914 // boolean isDollarPrefix = false;
915 // if (prefix.length() > 0 && prefix.charAt(0) == '$') {
916 // prefixWithoutDollar = prefix.substring(1);
917 // isDollarPrefix = true;
919 // IRegion region = new Region(start, end - start);
921 // if (!isDollarPrefix) {
922 // String[] tableNames = ExternalInterface.getMatchingTableNames(null,
923 // bookmarkString, prefixWithoutDollar, null, false);
924 // for (int i = 0; i < tableNames.length; i++) {
925 // sqlList.add(new SQLProposal(tableNames[i], context, region, viewer,
926 // PHPUiImages.get(PHPUiImages.IMG_TABLE)));
930 // String[] columnNames = ExternalInterface.getMatchingColumnNames(null,
931 // bookmarkString, prefixWithoutDollar, null, false);
932 // for (int i = 0; i < columnNames.length; i++) {
933 // sqlList.add(new SQLProposal(columnNames[i], context, region, viewer,
934 // PHPUiImages.get(PHPUiImages.IMG_TABLE)));
937 // sqlResults = new IPHPCompletionProposal[sqlList.size()];
938 // for (int i = 0; i < sqlList.size(); i++) {
939 // sqlResults[i] = (SQLProposal) sqlList.get(i);
941 // } catch (Exception /* NotConnectedException */ e) {
947 // return sqlResults;
949 private boolean looksLikeMethod(PHPCodeReader reader) throws IOException {
950 int curr = reader.read();
951 while (curr != PHPCodeReader.EOF && Character.isWhitespace((char) curr))
952 curr = reader.read();
954 if (curr == PHPCodeReader.EOF)
957 return Scanner.isPHPIdentifierPart((char) curr);
960 private int guessContextInformationPosition(ITextViewer viewer, int offset) {
961 int contextPosition = offset;
962 IDocument document = viewer.getDocument();
965 PHPCodeReader reader = new PHPCodeReader();
966 reader.configureBackwardReader(document, offset, true, true);
968 int nestingLevel = 0;
970 int curr = reader.read();
971 while (curr != PHPCodeReader.EOF) {
973 if (')' == (char) curr)
976 else if ('(' == (char) curr) {
979 if (nestingLevel < 0) {
980 int start = reader.getOffset();
981 if (looksLikeMethod(reader))
986 curr = reader.read();
988 } catch (IOException e) {
990 return contextPosition;
994 * @see IContentAssistProcessor#computeContextInformation(ITextViewer, int)
996 public IContextInformation[] computeContextInformation(ITextViewer viewer,
998 int contextInformationPosition = guessContextInformationPosition(
1000 List result = addContextInformations(viewer, contextInformationPosition);
1001 return (IContextInformation[]) result
1002 .toArray(new IContextInformation[result.size()]);
1005 private List addContextInformations(ITextViewer viewer, int offset) {
1006 ICompletionProposal[] proposals = internalComputeCompletionProposals(
1007 viewer, offset, -1);
1008 List result = new ArrayList();
1009 for (int i = 0; i < proposals.length; i++) {
1010 IContextInformation contextInformation = proposals[i]
1011 .getContextInformation();
1012 if (contextInformation != null) {
1013 ContextInformationWrapper wrapper = new ContextInformationWrapper(
1014 contextInformation);
1015 wrapper.setContextInformationPosition(offset);
1016 result.add(wrapper);
1023 * Order the given proposals.
1025 private ICompletionProposal[] order(ICompletionProposal[] proposals) {
1026 Arrays.sort(proposals, fComparator);
1027 // int len = proposals.length;
1031 // for (int i = 0; i < len; i++) {
1032 // System.out.println(proposals[i].getDisplayString());
1038 * (non-Javadoc) Method declared on IContentAssistProcessor
1040 public char[] getCompletionProposalAutoActivationCharacters() {
1041 return fProposalAutoActivationSet;
1042 // return null; // new char[] { '$' };
1046 * (non-Javadoc) Method declared on IContentAssistProcessor
1048 public char[] getContextInformationAutoActivationCharacters() {
1053 * (non-Javadoc) Method declared on IContentAssistProcessor
1055 public IContextInformationValidator getContextInformationValidator() {
1056 if (fValidator == null)
1057 fValidator = new JavaParameterListValidator();
1062 * (non-Javadoc) Method declared on IContentAssistProcessor
1064 public String getErrorMessage() {