KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > ui > text > java > ParameterGuessingProposal


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * Andrew McCullough - initial API and implementation
10  * IBM Corporation - general improvement and bug fixes, partial reimplementation
11  *******************************************************************************/

12 package org.eclipse.jdt.internal.ui.text.java;
13
14 import org.eclipse.core.runtime.Platform;
15
16 import org.eclipse.swt.graphics.Point;
17 import org.eclipse.swt.widgets.Shell;
18
19 import org.eclipse.jface.dialogs.MessageDialog;
20
21 import org.eclipse.jface.text.BadLocationException;
22 import org.eclipse.jface.text.BadPositionCategoryException;
23 import org.eclipse.jface.text.IDocument;
24 import org.eclipse.jface.text.IPositionUpdater;
25 import org.eclipse.jface.text.IRegion;
26 import org.eclipse.jface.text.Position;
27 import org.eclipse.jface.text.Region;
28 import org.eclipse.jface.text.contentassist.ICompletionProposal;
29 import org.eclipse.jface.text.link.ILinkedModeListener;
30 import org.eclipse.jface.text.link.InclusivePositionUpdater;
31 import org.eclipse.jface.text.link.LinkedModeModel;
32 import org.eclipse.jface.text.link.LinkedModeUI;
33 import org.eclipse.jface.text.link.LinkedPosition;
34 import org.eclipse.jface.text.link.LinkedPositionGroup;
35 import org.eclipse.jface.text.link.ProposalPosition;
36
37 import org.eclipse.ui.IEditorPart;
38 import org.eclipse.ui.texteditor.link.EditorLinkedModeUI;
39
40 import org.eclipse.jdt.core.CompletionProposal;
41 import org.eclipse.jdt.core.ICompilationUnit;
42 import org.eclipse.jdt.core.JavaModelException;
43 import org.eclipse.jdt.core.Signature;
44
45 import org.eclipse.jdt.internal.corext.template.java.SignatureUtil;
46 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
47
48 import org.eclipse.jdt.ui.text.java.JavaContentAssistInvocationContext;
49
50 import org.eclipse.jdt.internal.ui.JavaPlugin;
51 import org.eclipse.jdt.internal.ui.javaeditor.EditorHighlightingSynchronizer;
52 import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor;
53
54 /**
55  * This is a {@link org.eclipse.jdt.internal.ui.text.java.JavaCompletionProposal} which includes templates
56  * that represent the best guess completion for each parameter of a method.
57  */

58 public final class ParameterGuessingProposal extends JavaMethodCompletionProposal {
59
60     /** Tells whether this class is in debug mode. */
61     private static final boolean DEBUG= "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.jdt.ui/debug/ResultCollector")); //$NON-NLS-1$//$NON-NLS-2$
62

63     private ICompletionProposal[][] fChoices; // initialized by guessParameters()
64
private Position[] fPositions; // initialized by guessParameters()
65

66     private IRegion fSelectedRegion; // initialized by apply()
67
private IPositionUpdater fUpdater;
68
69     public ParameterGuessingProposal(CompletionProposal proposal, JavaContentAssistInvocationContext context) {
70         super(proposal, context);
71     }
72
73     /*
74      * @see ICompletionProposalExtension#apply(IDocument, char)
75      */

76     public void apply(IDocument document, char trigger, int offset) {
77         try {
78             super.apply(document, trigger, offset);
79             
80             int baseOffset= getReplacementOffset();
81             String JavaDoc replacement= getReplacementString();
82             
83             if (fPositions != null && getTextViewer() != null) {
84                 
85                 LinkedModeModel model= new LinkedModeModel();
86                 
87                 for (int i= 0; i < fPositions.length; i++) {
88                     LinkedPositionGroup group= new LinkedPositionGroup();
89                     int positionOffset= fPositions[i].getOffset();
90                     int positionLength= fPositions[i].getLength();
91                 
92                     if (fChoices[i].length < 2) {
93                         group.addPosition(new LinkedPosition(document, positionOffset, positionLength, LinkedPositionGroup.NO_STOP));
94                     } else {
95                         ensurePositionCategoryInstalled(document, model);
96                         document.addPosition(getCategory(), fPositions[i]);
97                         group.addPosition(new ProposalPosition(document, positionOffset, positionLength, LinkedPositionGroup.NO_STOP, fChoices[i]));
98                     }
99                     model.addGroup(group);
100                 }
101
102                 model.forceInstall();
103                 JavaEditor editor= getJavaEditor();
104                 if (editor != null) {
105                     model.addLinkingListener(new EditorHighlightingSynchronizer(editor));
106                 }
107
108                 LinkedModeUI ui= new EditorLinkedModeUI(model, getTextViewer());
109                 ui.setExitPosition(getTextViewer(), baseOffset + replacement.length(), 0, Integer.MAX_VALUE);
110                 ui.setExitPolicy(new ExitPolicy(')', document));
111                 ui.setCyclingMode(LinkedModeUI.CYCLE_WHEN_NO_PARENT);
112                 ui.setDoContextInfo(true);
113                 ui.enter();
114                 fSelectedRegion= ui.getSelectedRegion();
115
116             } else {
117                 fSelectedRegion= new Region(baseOffset + replacement.length(), 0);
118             }
119
120         } catch (BadLocationException e) {
121             ensurePositionCategoryRemoved(document);
122             JavaPlugin.log(e);
123             openErrorDialog(e);
124         } catch (BadPositionCategoryException e) {
125             ensurePositionCategoryRemoved(document);
126             JavaPlugin.log(e);
127             openErrorDialog(e);
128         }
129     }
130     
131     /*
132      * @see org.eclipse.jdt.internal.ui.text.java.JavaMethodCompletionProposal#needsLinkedMode()
133      */

134     protected boolean needsLinkedMode() {
135         return false; // we handle it ourselves
136
}
137     
138     /*
139      * @see org.eclipse.jdt.internal.ui.text.java.JavaMethodCompletionProposal#computeReplacementString()
140      */

141     protected String JavaDoc computeReplacementString() {
142         
143         if (!hasParameters() || !hasArgumentList())
144             return super.computeReplacementString();
145         
146         long millis= DEBUG ? System.currentTimeMillis() : 0;
147         String JavaDoc replacement;
148         try {
149             replacement= computeGuessingCompletion();
150         } catch (JavaModelException x) {
151             fPositions= null;
152             fChoices= null;
153             JavaPlugin.log(x);
154             openErrorDialog(x);
155             return super.computeReplacementString();
156         }
157         if (DEBUG) System.err.println("Parameter Guessing: " + (System.currentTimeMillis() - millis)); //$NON-NLS-1$
158

159         return replacement;
160     }
161
162     /**
163      * Creates the completion string. Offsets and Lengths are set to the offsets and lengths
164      * of the parameters.
165      */

166     private String JavaDoc computeGuessingCompletion() throws JavaModelException {
167         
168         StringBuffer JavaDoc buffer= new StringBuffer JavaDoc(String.valueOf(fProposal.getName()));
169         
170         FormatterPrefs prefs= getFormatterPrefs();
171         if (prefs.beforeOpeningParen)
172             buffer.append(SPACE);
173         buffer.append(LPAREN);
174         
175         setCursorPosition(buffer.length());
176         
177         if (prefs.afterOpeningParen)
178             buffer.append(SPACE);
179         
180         fChoices= guessParameters();
181         int count= fChoices.length;
182         int replacementOffset= getReplacementOffset();
183         
184         for (int i= 0; i < count; i++) {
185             if (i != 0) {
186                 if (prefs.beforeComma)
187                     buffer.append(SPACE);
188                 buffer.append(COMMA);
189                 if (prefs.afterComma)
190                     buffer.append(SPACE);
191             }
192
193             ICompletionProposal proposal= fChoices[i][0];
194             String JavaDoc argument= proposal.getDisplayString();
195             Position position= fPositions[i];
196             position.setOffset(replacementOffset + buffer.length());
197             position.setLength(argument.length());
198             if (proposal instanceof JavaCompletionProposal) // handle the "unknown" case where we only insert a proposal.
199
((JavaCompletionProposal) proposal).setReplacementOffset(replacementOffset + buffer.length());
200             buffer.append(argument);
201         }
202         
203         if (prefs.beforeClosingParen)
204             buffer.append(SPACE);
205
206         buffer.append(RPAREN);
207
208         return buffer.toString();
209     }
210     
211     /**
212      * Returns the currently active java editor, or <code>null</code> if it
213      * cannot be determined.
214      *
215      * @return the currently active java editor, or <code>null</code>
216      */

217     private JavaEditor getJavaEditor() {
218         IEditorPart part= JavaPlugin.getActivePage().getActiveEditor();
219         if (part instanceof JavaEditor)
220             return (JavaEditor) part;
221         else
222             return null;
223     }
224
225     private ICompletionProposal[][] guessParameters() throws JavaModelException {
226         // find matches in reverse order. Do this because people tend to declare the variable meant for the last
227
// parameter last. That is, local variables for the last parameter in the method completion are more
228
// likely to be closer to the point of code completion. As an example consider a "delegation" completion:
229
//
230
// public void myMethod(int param1, int param2, int param3) {
231
// someOtherObject.yourMethod(param1, param2, param3);
232
// }
233
//
234
// The other consideration is giving preference to variables that have not previously been used in this
235
// code completion (which avoids "someOtherObject.yourMethod(param1, param1, param1)";
236

237         char[][] parameterNames= fProposal.findParameterNames(null);
238         int count= parameterNames.length;
239         fPositions= new Position[count];
240         fChoices= new ICompletionProposal[count][];
241
242         IDocument document= fInvocationContext.getDocument();
243         ICompilationUnit cu= fInvocationContext.getCompilationUnit();
244         JavaModelUtil.reconcile(cu);
245         String JavaDoc[][] parameterTypes= getParameterSignatures();
246         ParameterGuesser guesser= new ParameterGuesser(fProposal.getCompletionLocation() + 1, cu);
247         
248         for (int i= count - 1; i >= 0; i--) {
249             String JavaDoc paramName= new String JavaDoc(parameterNames[i]);
250             Position position= new Position(0,0);
251             
252             ICompletionProposal[] argumentProposals= guesser.parameterProposals(parameterTypes[i][0], parameterTypes[i][1], paramName, position, document);
253             if (argumentProposals.length == 0)
254                 argumentProposals= new ICompletionProposal[] {new JavaCompletionProposal(paramName, 0, paramName.length(), null, paramName, 0)};
255             
256             fPositions[i]= position;
257             fChoices[i]= argumentProposals;
258         }
259         
260         return fChoices;
261     }
262
263     private String JavaDoc[][] getParameterSignatures() {
264         char[] signature= SignatureUtil.fix83600(fProposal.getSignature());
265         char[][] types= Signature.getParameterTypes(signature);
266         String JavaDoc[][] ret= new String JavaDoc[types.length][2];
267
268         for (int i= 0; i < types.length; i++) {
269             char[] type= SignatureUtil.getLowerBound(types[i]);
270             ret[i][0]= String.valueOf(Signature.getSignatureQualifier(type));
271             ret[i][1]= String.valueOf(Signature.getSignatureSimpleName(type));
272         }
273         return ret;
274     }
275
276     /*
277      * @see ICompletionProposal#getSelection(IDocument)
278      */

279     public Point getSelection(IDocument document) {
280         if (fSelectedRegion == null)
281             return new Point(getReplacementOffset(), 0);
282
283         return new Point(fSelectedRegion.getOffset(), fSelectedRegion.getLength());
284     }
285
286     private void openErrorDialog(Exception JavaDoc e) {
287         Shell shell= getTextViewer().getTextWidget().getShell();
288         MessageDialog.openError(shell, JavaTextMessages.ParameterGuessingProposal_error_msg, e.getMessage());
289     }
290
291     private void ensurePositionCategoryInstalled(final IDocument document, LinkedModeModel model) {
292         if (!document.containsPositionCategory(getCategory())) {
293             document.addPositionCategory(getCategory());
294             fUpdater= new InclusivePositionUpdater(getCategory());
295             document.addPositionUpdater(fUpdater);
296
297             model.addLinkingListener(new ILinkedModeListener() {
298
299                 /*
300                  * @see org.eclipse.jface.text.link.ILinkedModeListener#left(org.eclipse.jface.text.link.LinkedModeModel, int)
301                  */

302                 public void left(LinkedModeModel environment, int flags) {
303                     ensurePositionCategoryRemoved(document);
304                 }
305
306                 public void suspend(LinkedModeModel environment) {}
307                 public void resume(LinkedModeModel environment, int flags) {}
308             });
309         }
310     }
311
312     private void ensurePositionCategoryRemoved(IDocument document) {
313         if (document.containsPositionCategory(getCategory())) {
314             try {
315                 document.removePositionCategory(getCategory());
316             } catch (BadPositionCategoryException e) {
317                 // ignore
318
}
319             document.removePositionUpdater(fUpdater);
320         }
321     }
322
323     private String JavaDoc getCategory() {
324         return "ParameterGuessingProposal_" + toString(); //$NON-NLS-1$
325
}
326
327 }
328
Popular Tags