c7ad06a280494bd43b38e5414c33259ef4cfa94c
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpeclipse / phpeditor / php / PHPCompletionProcessor.java
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
7
8 Contributors:
9     IBM Corporation - Initial implementation
10     Klaus Hartlage - www.eclipseproject.de
11 **********************************************************************/
12 package net.sourceforge.phpeclipse.phpeditor.php;
13
14 import java.text.MessageFormat;
15 import java.util.ArrayList;
16 import java.util.Arrays;
17 import java.util.List;
18
19 import net.sourceforge.phpdt.internal.corext.template.ContextType;
20 import net.sourceforge.phpdt.internal.corext.template.ContextTypeRegistry;
21 import net.sourceforge.phpdt.internal.ui.text.java.IJavaCompletionProposal;
22 import net.sourceforge.phpdt.internal.ui.text.java.JavaCompletionProposalComparator;
23 import net.sourceforge.phpdt.internal.ui.text.template.TemplateEngine;
24 import org.eclipse.jface.text.BadLocationException;
25 import org.eclipse.jface.text.IDocument;
26 import org.eclipse.jface.text.ITextViewer;
27 import org.eclipse.jface.text.TextPresentation;
28 import org.eclipse.jface.text.contentassist.CompletionProposal;
29 import org.eclipse.jface.text.contentassist.ContextInformation;
30 import org.eclipse.jface.text.contentassist.ICompletionProposal;
31 import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
32 import org.eclipse.jface.text.contentassist.IContextInformation;
33 import org.eclipse.jface.text.contentassist.IContextInformationExtension;
34 import org.eclipse.jface.text.contentassist.IContextInformationPresenter;
35 import org.eclipse.jface.text.contentassist.IContextInformationValidator;
36 import org.eclipse.swt.graphics.Image;
37
38 /**
39  * Example PHP completion processor.
40  */
41 public class PHPCompletionProcessor implements IContentAssistProcessor {
42
43   /**
44    * Simple content assist tip closer. The tip is valid in a range
45    * of 5 characters around its popup location.
46    */
47   protected static class Validator implements IContextInformationValidator, IContextInformationPresenter {
48
49     protected int fInstallOffset;
50
51     /*
52      * @see IContextInformationValidator#isContextInformationValid(int)
53      */
54     public boolean isContextInformationValid(int offset) {
55       return Math.abs(fInstallOffset - offset) < 5;
56     }
57
58     /*
59      * @see IContextInformationValidator#install(IContextInformation, ITextViewer, int)
60      */
61     public void install(IContextInformation info, ITextViewer viewer, int offset) {
62       fInstallOffset = offset;
63     }
64
65     /*
66      * @see org.eclipse.jface.text.contentassist.IContextInformationPresenter#updatePresentation(int, TextPresentation)
67      */
68     public boolean updatePresentation(int documentPosition, TextPresentation presentation) {
69       return false;
70     }
71   };
72
73   private static class ContextInformationWrapper implements IContextInformation, IContextInformationExtension {
74
75     private final IContextInformation fContextInformation;
76     private int fPosition;
77
78     public ContextInformationWrapper(IContextInformation contextInformation) {
79       fContextInformation = contextInformation;
80     }
81
82     /*
83      * @see IContextInformation#getContextDisplayString()
84      */
85     public String getContextDisplayString() {
86       return fContextInformation.getContextDisplayString();
87     }
88
89     /*
90     * @see IContextInformation#getImage()
91     */
92     public Image getImage() {
93       return fContextInformation.getImage();
94     }
95
96     /*
97      * @see IContextInformation#getInformationDisplayString()
98      */
99     public String getInformationDisplayString() {
100       return fContextInformation.getInformationDisplayString();
101     }
102
103     /*
104      * @see IContextInformationExtension#getContextInformationPosition()
105      */
106     public int getContextInformationPosition() {
107       return fPosition;
108     }
109
110     public void setContextInformationPosition(int position) {
111       fPosition = position;
112     }
113   };
114
115   protected final static String[] fgProposals = PHPFunctionNames.FUNCTION_NAMES;
116   //    {
117   //      "array",
118   //      "break",
119   //      "class",
120   //      "continue",
121   //      "do",
122   //      "echo",
123   //      "else",
124   //      "elseif",
125   //      "endfor",
126   //      "endif",
127   //      "for",
128   //      "if",
129   //      "while",
130   //      "endwhile",
131   //      "switch",
132   //      "case",
133   //      "endswitch",
134   //      "return",
135   //      "define",
136   //      "include",
137   //      "include_once",
138   //      "require",
139   //      "require_once",
140   //      "function",
141   //      "new",
142   //      "old_function",
143   //      "default",
144   //      "global",
145   //      "static",
146   //      "foreach",
147   //      "endforeach",
148   //      "extends",
149   //      "empty",
150   //      "isset",
151   //      "var" };
152
153   protected IContextInformationValidator fValidator = new Validator();
154   private TemplateEngine fTemplateEngine;
155   private JavaCompletionProposalComparator fComparator;
156   private int fNumberOfComputedResults = 0;
157
158   public PHPCompletionProcessor() {
159
160     ContextType contextType = ContextTypeRegistry.getInstance().getContextType("php"); //$NON-NLS-1$
161     if (contextType != null)
162       fTemplateEngine = new TemplateEngine(contextType);
163
164     fComparator = new JavaCompletionProposalComparator();
165   }
166   /* (non-Javadoc)
167    * Method declared on IContentAssistProcessor
168    */
169   public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int documentOffset) {
170     //    IDocument document = viewer.getDocument();
171     //    if (documentOffset > 0) {
172     //      try {
173     //        ICompletionProposal[] result;
174     //        char character = document.getChar(documentOffset - 1);
175     //        if (character == '$') {
176     ////viewer.  .getActivePage().getActiveEditor();
177     //          result = new ICompletionProposal[fgProposals.length];
178     //          for (int i = 0; i < fgProposals.length; i++) {
179     //            IContextInformation info = new ContextInformation(fgProposals[i], MessageFormat.format(PHPEditorMessages.getString("CompletionProcessor.Proposal.ContextInfo.pattern"), new Object[] { fgProposals[i] })); //$NON-NLS-1$
180     //            result[i] = new CompletionProposal(fgProposals[i], documentOffset, 0, fgProposals[i].length(), null, fgProposals[i], info, MessageFormat.format(PHPEditorMessages.getString("CompletionProcessor.Proposal.hoverinfo.pattern"), new Object[] { fgProposals[i] })); //$NON-NLS-1$
181     //          }
182     //          return result;
183     //        }
184     //      } catch (BadLocationException e) {
185     //        return new ICompletionProposal[0];
186     //      }
187     //    }
188     //
189     //    ICompletionProposal[] result = new ICompletionProposal[fgProposals.length];
190     //    for (int i = 0; i < fgProposals.length; i++) {
191     //      IContextInformation info = new ContextInformation(fgProposals[i], MessageFormat.format(PHPEditorMessages.getString("CompletionProcessor.Proposal.ContextInfo.pattern"), new Object[] { fgProposals[i] })); //$NON-NLS-1$
192     //      result[i] = new CompletionProposal(fgProposals[i], documentOffset, 0, fgProposals[i].length(), null, fgProposals[i], info, MessageFormat.format(PHPEditorMessages.getString("CompletionProcessor.Proposal.hoverinfo.pattern"), new Object[] { fgProposals[i] })); //$NON-NLS-1$
193     //    }
194     //    return result;
195     int contextInformationPosition = guessContextInformationPosition(viewer, documentOffset);
196     return internalComputeCompletionProposals(viewer, documentOffset, contextInformationPosition);
197
198   }
199
200   private ICompletionProposal[] internalComputeCompletionProposals(ITextViewer viewer, int offset, int contextOffset) {
201     IDocument document = viewer.getDocument();
202     if (offset > 0) {
203       try {
204         ICompletionProposal[] result;
205         char character = document.getChar(offset - 1);
206         if (character == '$') {
207           //viewer.  .getActivePage().getActiveEditor();
208           result = new ICompletionProposal[fgProposals.length];
209           for (int i = 0; i < fgProposals.length; i++) {
210             IContextInformation info = new ContextInformation(fgProposals[i], MessageFormat.format(PHPEditorMessages.getString("CompletionProcessor.Proposal.ContextInfo.pattern"), new Object[] { fgProposals[i] })); //$NON-NLS-1$
211             result[i] = new CompletionProposal(fgProposals[i], offset, 0, fgProposals[i].length(), null, fgProposals[i], info, MessageFormat.format(PHPEditorMessages.getString("CompletionProcessor.Proposal.hoverinfo.pattern"), new Object[] { fgProposals[i] })); //$NON-NLS-1$
212           }
213           return result;
214         }
215       } catch (BadLocationException e) {
216         return new ICompletionProposal[0];
217       }
218     }
219
220     if (fTemplateEngine != null) {
221       IJavaCompletionProposal[] results;
222       //      try {
223       fTemplateEngine.reset();
224       fTemplateEngine.complete(viewer, offset); //, unit);
225       //      } catch (JavaModelException x) {
226       //        Shell shell= viewer.getTextWidget().getShell();
227       //        ErrorDialog.openError(shell, JavaTextMessages.getString("CompletionProcessor.error.accessing.title"), JavaTextMessages.getString("CompletionProcessor.error.accessing.message"), x.getStatus()); //$NON-NLS-2$ //$NON-NLS-1$
228       //      }       
229
230       IJavaCompletionProposal[] templateResults = fTemplateEngine.getResults();
231
232       // concatenate arrays
233       IJavaCompletionProposal[] total = new IJavaCompletionProposal[templateResults.length]; // +results.length ];
234       System.arraycopy(templateResults, 0, total, 0, templateResults.length);
235       //      System.arraycopy(results, 0, total, templateResults.length, results.length);
236       results = total;
237       //    }
238
239       fNumberOfComputedResults = (results == null ? 0 : results.length);
240
241       /*
242        * Order here and not in result collector to make sure that the order
243        * applies to all proposals and not just those of the compilation unit. 
244        */
245       return order(results);
246     }
247     return new IJavaCompletionProposal[0];
248   }
249
250   private int guessContextInformationPosition(ITextViewer viewer, int offset) {
251     int contextPosition = offset;
252
253     IDocument document = viewer.getDocument();
254
255     //    try {
256     //
257     //      JavaCodeReader reader= new JavaCodeReader();
258     //      reader.configureBackwardReader(document, offset, true, true);
259     //  
260     //      int nestingLevel= 0;
261     //
262     //      int curr= reader.read();    
263     //      while (curr != JavaCodeReader.EOF) {
264     //
265     //        if (')' == (char) curr)
266     //          ++ nestingLevel;
267     //
268     //        else if ('(' == (char) curr) {
269     //          -- nestingLevel;
270     //        
271     //          if (nestingLevel < 0) {
272     //            int start= reader.getOffset();
273     //            if (looksLikeMethod(reader))
274     //              return start + 1;
275     //          } 
276     //        }
277     //
278     //        curr= reader.read();          
279     //      }
280     //    } catch (IOException e) {
281     //    }
282
283     return contextPosition;
284   }
285
286   /* (non-Javadoc)
287    * Method declared on IContentAssistProcessor
288    */
289   //  public IContextInformation[] computeContextInformation(ITextViewer viewer, int documentOffset) {
290   //    IContextInformation[] result = new IContextInformation[5];
291   //    for (int i = 0; i < result.length; i++)
292   //      result[i] = new ContextInformation(MessageFormat.format(PHPEditorMessages.getString("CompletionProcessor.ContextInfo.display.pattern"), new Object[] { new Integer(i), new Integer(documentOffset)}), //$NON-NLS-1$
293   //      MessageFormat.format(PHPEditorMessages.getString("CompletionProcessor.ContextInfo.value.pattern"), new Object[] { new Integer(i), new Integer(documentOffset - 5), new Integer(documentOffset + 5)})); //$NON-NLS-1$
294   //    return result;
295   //  }
296   /**
297    * @see IContentAssistProcessor#computeContextInformation(ITextViewer, int)
298    */
299   public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) {
300     int contextInformationPosition = guessContextInformationPosition(viewer, offset);
301     List result = addContextInformations(viewer, contextInformationPosition);
302     return (IContextInformation[]) result.toArray(new IContextInformation[result.size()]);
303   }
304
305   private List addContextInformations(ITextViewer viewer, int offset) {
306     ICompletionProposal[] proposals = internalComputeCompletionProposals(viewer, offset, -1);
307
308     List result = new ArrayList();
309     for (int i = 0; i < proposals.length; i++) {
310       IContextInformation contextInformation = proposals[i].getContextInformation();
311       if (contextInformation != null) {
312         ContextInformationWrapper wrapper = new ContextInformationWrapper(contextInformation);
313         wrapper.setContextInformationPosition(offset);
314         result.add(wrapper);
315       }
316     }
317     return result;
318   }
319
320   /**
321    * Order the given proposals.
322    */
323   private ICompletionProposal[] order(ICompletionProposal[] proposals) {
324     Arrays.sort(proposals, fComparator);
325     return proposals;
326   }
327
328   /* (non-Javadoc)
329    * Method declared on IContentAssistProcessor
330    */
331   public char[] getCompletionProposalAutoActivationCharacters() {
332     return new char[] { '$' };
333   }
334
335   /* (non-Javadoc)
336    * Method declared on IContentAssistProcessor
337    */
338   public char[] getContextInformationAutoActivationCharacters() {
339     return new char[] {
340     };
341   }
342
343   /* (non-Javadoc)
344    * Method declared on IContentAssistProcessor
345    */
346   public IContextInformationValidator getContextInformationValidator() {
347     return fValidator;
348   }
349
350   /* (non-Javadoc)
351    * Method declared on IContentAssistProcessor
352    */
353   public String getErrorMessage() {
354     return null;
355   }
356 }