Fix Request #1431769: Support Context assistance when entering functions arguments
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / ui / text / template / DeclarationProposal.java
1 /*
2  * (c) Copyright IBM Corp. 2000, 2001.
3  * All Rights Reserved.
4  */
5 package net.sourceforge.phpdt.internal.ui.text.template;
6
7 import net.sourceforge.phpdt.internal.corext.phpdoc.PHPDocUtil;
8 import net.sourceforge.phpdt.internal.corext.template.TemplateMessages;
9 import net.sourceforge.phpdt.internal.corext.template.php.JavaContext;
10 import net.sourceforge.phpdt.internal.ui.PHPUiImages;
11 import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionManager;
12 import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionUI;
13 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
14 import net.sourceforge.phpeclipse.builder.PHPIdentifierLocation;
15
16 import org.eclipse.core.resources.IProject;
17 import org.eclipse.jface.text.BadLocationException;
18 import org.eclipse.jface.text.IDocument;
19 import org.eclipse.jface.text.IRegion;
20 import org.eclipse.jface.text.ITextViewer;
21 import org.eclipse.jface.text.contentassist.ContextInformation;
22 import org.eclipse.jface.text.contentassist.IContextInformation;
23 import org.eclipse.jface.text.templates.TemplateContext;
24 import org.eclipse.swt.graphics.Image;
25
26 // import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionManager;
27 // import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionUI;
28 // import net.sourceforge.phpdt.internal.ui.util.ExceptionHandler;
29
30 /**
31  * A PHP identifier proposal.
32  */
33 public class DeclarationProposal extends AbstractProposal { // implements
34         // IPHPCompletionProposal
35         // {
36         private IProject fProject;
37
38         private final TemplateContext fContext;
39
40         private final PHPIdentifierLocation fLocation;
41
42         String fInfo;
43
44         // private TemplateBuffer fTemplateBuffer;
45         // private String fOldText;
46         // private final Image fImage_fun;
47         // private final Image fImage_var;
48         private final IRegion fRegion;
49
50         // private IRegion fSelectedRegion; // initialized by apply()
51
52         private final String fIdentifierName;
53
54         // private final ITextViewer fViewer;
55
56         /**
57          * Creates a template proposal with a template and its context.
58          *
59          * @param template
60          *          the template
61          * @param context
62          *          the context in which the template was requested.
63          * @param image
64          *          the icon of the proposal.
65          */
66         public DeclarationProposal(IProject project, String identifierName, PHPIdentifierLocation location, TemplateContext context,
67                         IRegion region, ITextViewer viewer) {
68                 super(viewer);
69                 // Image image_fun,
70                 // Image image_var) {
71                 fProject = project;
72                 fIdentifierName = identifierName;
73                 fLocation = location;
74                 fContext = context;
75                 fRegion = region;
76                 fInfo = null;
77         }
78
79         /*
80          * @see ICompletionProposal#apply(IDocument)
81          */
82         public void apply(IDocument document) {
83                 try {
84                         // if (fTemplateBuffer == null)
85                         // fTemplateBuffer= fContext.evaluate(fTemplate);
86
87                         int start = fRegion.getOffset();
88                         int end = fRegion.getOffset() + fRegion.getLength();
89
90                         switch (fLocation.getType()) {
91                         case PHPIdentifierLocation.FUNCTION:
92                                 document.replace(start, end - start, fIdentifierName + "()");
93                                 break;
94                         case PHPIdentifierLocation.CONSTRUCTOR:
95                                 document.replace(start, end - start, fIdentifierName + "()");
96                                 break;
97                         case PHPIdentifierLocation.METHOD:
98                                 document.replace(start, end - start, fIdentifierName + "()");
99                                 break;
100
101                         default:
102                                 document.replace(start, end - start, fIdentifierName);
103                         }
104
105                         // translate positions
106                         LinkedPositionManager manager = new LinkedPositionManager(document);
107                         // TemplatePosition[] variables= fTemplateBuffer.getVariables();
108                         // for (int i= 0; i != variables.length; i++) {
109                         // TemplatePosition variable= variables[i];
110                         //
111                         // if (variable.isResolved())
112                         // continue;
113                         //
114                         // int[] offsets= variable.getOffsets();
115                         // int length= variable.getLength();
116                         //
117                         // for (int j= 0; j != offsets.length; j++)
118                         // manager.addPosition(offsets[j] + start, length);
119                         // }
120
121                         LinkedPositionUI editor = new LinkedPositionUI(fViewer, manager);
122                         switch (fLocation.getType()) {
123                         case PHPIdentifierLocation.FUNCTION:
124                                 editor.setFinalCaretOffset(fIdentifierName.length() + start + 1);
125                                 break;
126                         case PHPIdentifierLocation.CONSTRUCTOR:
127                                 editor.setFinalCaretOffset(fIdentifierName.length() + start + 1);
128                                 break;
129                         case PHPIdentifierLocation.METHOD:
130                                 editor.setFinalCaretOffset(fIdentifierName.length() + start + 1);
131                                 break;
132
133                         default:
134                                 editor.setFinalCaretOffset(fIdentifierName.length() + start);
135                         }
136                         editor.enter();
137
138                         fSelectedRegion = editor.getSelectedRegion();
139
140                 } catch (BadLocationException e) {
141                         PHPeclipsePlugin.log(e);
142                         openErrorDialog(e);
143
144                 }
145                 // catch (CoreException e) {
146                 // handleException(e);
147                 // }
148         }
149
150         /*
151          * @see ICompletionProposal#getAdditionalProposalInfo()
152          */
153         public String getAdditionalProposalInfo() {
154                 if (fInfo == null) {
155                         fInfo = computeProposalInfo();
156                 }
157                 return fInfo;
158         }
159
160         private String computeProposalInfo() {
161                 StringBuffer hoverInfoBuffer = new StringBuffer();
162                 // String workspaceLocation =
163                 // PHPeclipsePlugin.getWorkspace().getRoot().getLocation().toString();
164                 String workspaceLocation;
165                 if (fProject != null) {
166                         workspaceLocation = fProject.getLocation().toString() + '/';
167                 } else {
168                         // should never happen?
169                         workspaceLocation = PHPeclipsePlugin.getWorkspace().getRoot().getLocation().toString();
170                 }
171                 String filename = workspaceLocation + fLocation.getFilename();
172                 PHPDocUtil.appendPHPDoc(hoverInfoBuffer, filename, fLocation);
173                 return hoverInfoBuffer.toString();
174         }
175
176         public IContextInformation getContextInformation() {
177                 if (fContextInfo == null) {
178                         if (fLocation != null) {
179                                 fInfo = fLocation.getUsage();
180                                 if (fInfo != null) {
181                                         // extract the parameter context information for the function:
182                                         int i0 = fInfo.indexOf('(');
183                                         int newline = fInfo.indexOf('\n');
184                                         if (i0 >= 0 && (i0 < newline || newline < 0)) {
185                                                 int i1 = fInfo.indexOf(')', i0 + 1);
186                                                 if (i1 > 0) {
187
188                                                         fContextInfo = new ContextInformation(null, fInfo.substring(i0+1, i1));
189                                                 } else {
190                                                         fContextInfo = new ContextInformation(null, fInfo);
191                                                 }
192                                         } else {
193                                                 fContextInfo = new ContextInformation(null, fInfo);
194                                         }
195                                 }
196                         }
197                 }
198                 return fContextInfo;
199         }
200
201         /*
202          * @see ICompletionProposal#getDisplayString()
203          */
204         public String getDisplayString() {
205                 String workspaceLocation;
206                 if (fProject != null) {
207                         workspaceLocation = fProject.getName().toString() + '/';
208                 } else {
209                         // should never happen?
210                         workspaceLocation = PHPeclipsePlugin.getWorkspace().getRoot().getLocation().toString();
211                 }
212                 String filename = workspaceLocation + fLocation.getFilename();
213                 String usage = PHPDocUtil.getUsage(filename, fLocation);
214                 String result = fIdentifierName + TemplateMessages.getString("TemplateProposal.delimiter");
215                 if (usage.length() > 0) {
216                         result += usage + TemplateMessages.getString("TemplateProposal.delimiter");
217                 }
218                 result += filename;
219                 return result;
220         }
221
222         /*
223          * @see ICompletionProposal#getImage()
224          */
225         public Image getImage() {
226                 switch (fLocation.getType()) {
227                 case PHPIdentifierLocation.FUNCTION:
228                         return PHPUiImages.get(PHPUiImages.IMG_FUN);
229                 case PHPIdentifierLocation.CLASS:
230                         return PHPUiImages.get(PHPUiImages.IMG_CLASS);
231                 case PHPIdentifierLocation.CONSTRUCTOR:
232                         return PHPUiImages.get(PHPUiImages.IMG_CLASS);
233                 case PHPIdentifierLocation.METHOD:
234                         return PHPUiImages.get(PHPUiImages.IMG_FUN);
235                 case PHPIdentifierLocation.DEFINE:
236                         return PHPUiImages.get(PHPUiImages.IMG_DEFINE);
237                 case PHPIdentifierLocation.VARIABLE:
238                         return PHPUiImages.get(PHPUiImages.IMG_VAR);
239                 case PHPIdentifierLocation.GLOBAL_VARIABLE:
240                         return PHPUiImages.get(PHPUiImages.IMG_VAR);
241                 }
242                 return PHPUiImages.get(PHPUiImages.IMG_FUN);
243         }
244
245         /*
246          * @see IJavaCompletionProposal#getRelevance()
247          */
248         public int getRelevance() {
249
250                 if (fContext instanceof JavaContext) {
251                         JavaContext context = (JavaContext) fContext;
252                         switch (context.getCharacterBeforeStart()) {
253                         // high relevance after whitespace
254                         case ' ':
255                         case '\r':
256                         case '\n':
257                         case '\t':
258                                 return 80;
259                         case '>': // ->
260                         case ':': // ::
261                                 return 85;
262                         default:
263                                 return 0;
264                         }
265                 } else {
266                         return 80;
267                 }
268         }
269
270 }