KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > texteditor > RegExContentAssistProcessor


1 /*******************************************************************************
2  * Copyright (c) 2000, 2005 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  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.ui.texteditor;
13
14 import java.util.ArrayList JavaDoc;
15
16 import org.eclipse.jface.contentassist.IContentAssistSubjectControl;
17 import org.eclipse.jface.contentassist.ISubjectControlContentAssistProcessor;
18 import org.eclipse.jface.contentassist.SubjectControlContextInformationValidator;
19 import org.eclipse.jface.text.ITextViewer;
20 import org.eclipse.jface.text.contentassist.CompletionProposal;
21 import org.eclipse.jface.text.contentassist.ICompletionProposal;
22 import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
23 import org.eclipse.jface.text.contentassist.IContextInformation;
24 import org.eclipse.jface.text.contentassist.IContextInformationValidator;
25
26 /**
27  * Content assist processor for regular expressions.
28  *
29  * @since 3.0
30  */

31 final class RegExContentAssistProcessor implements IContentAssistProcessor, ISubjectControlContentAssistProcessor {
32
33     /**
34      * Proposal computer.
35      *
36      * @since 3.1
37      */

38     private static class ProposalComputer {
39
40         /**
41          * The whole regular expression.
42          */

43         private final String JavaDoc fExpression;
44         /**
45          * The document offset.
46          */

47         private final int fDocumentOffset;
48         /**
49          * The high-priority proposals.
50          */

51         private final ArrayList JavaDoc fPriorityProposals;
52         /**
53          * The low-priority proposals.
54          */

55         private final ArrayList JavaDoc fProposals;
56         /**
57          * <code>true</code> iff <code>fExpression</code> ends with an open escape.
58          */

59         private final boolean fIsEscape;
60
61         /**
62          * Creates a new Proposal Computer.
63          * @param contentAssistSubjectControl the subject control
64          * @param documentOffset the offset
65          */

66         public ProposalComputer(IContentAssistSubjectControl contentAssistSubjectControl, int documentOffset) {
67             fExpression= contentAssistSubjectControl.getDocument().get();
68             fDocumentOffset= documentOffset;
69             fPriorityProposals= new ArrayList JavaDoc();
70             fProposals= new ArrayList JavaDoc();
71             
72             boolean isEscape= false;
73             esc: for (int i= documentOffset - 1; i >= 0; i--) {
74                 if (fExpression.charAt(i) == '\\')
75                     isEscape= !isEscape;
76                 else
77                     break esc;
78             }
79             fIsEscape= isEscape;
80         }
81
82         /**
83          * Computes applicable proposals for the find field.
84          * @return the proposals
85          */

86         public ICompletionProposal[] computeFindProposals() {
87             //characters
88
addBsProposal("\\\\", RegExMessages.displayString_bs_bs, RegExMessages.additionalInfo_bs_bs); //$NON-NLS-1$
89
addBracketProposal("\\0", 2, RegExMessages.displayString_bs_0, RegExMessages.additionalInfo_bs_0); //$NON-NLS-1$
90
addBracketProposal("\\x", 2, RegExMessages.displayString_bs_x, RegExMessages.additionalInfo_bs_x); //$NON-NLS-1$
91
addBracketProposal("\\u", 2, RegExMessages.displayString_bs_u, RegExMessages.additionalInfo_bs_u); //$NON-NLS-1$
92
addBsProposal("\\t", RegExMessages.displayString_bs_t, RegExMessages.additionalInfo_bs_t); //$NON-NLS-1$
93
addBsProposal("\\n", RegExMessages.displayString_bs_n, RegExMessages.additionalInfo_bs_n); //$NON-NLS-1$
94
addBsProposal("\\r", RegExMessages.displayString_bs_r, RegExMessages.additionalInfo_bs_r); //$NON-NLS-1$
95
addBsProposal("\\f", RegExMessages.displayString_bs_f, RegExMessages.additionalInfo_bs_f); //$NON-NLS-1$
96
addBsProposal("\\a", RegExMessages.displayString_bs_a, RegExMessages.additionalInfo_bs_a); //$NON-NLS-1$
97
addBsProposal("\\e", RegExMessages.displayString_bs_e, RegExMessages.additionalInfo_bs_e); //$NON-NLS-1$
98
addBsProposal("\\c", RegExMessages.displayString_bs_c, RegExMessages.additionalInfo_bs_c); //$NON-NLS-1$
99

100             if (! fIsEscape)
101                 addBracketProposal(".", 1, RegExMessages.displayString_dot, RegExMessages.additionalInfo_dot); //$NON-NLS-1$
102
addBsProposal("\\d", RegExMessages.displayString_bs_d, RegExMessages.additionalInfo_bs_d); //$NON-NLS-1$
103
addBsProposal("\\D", RegExMessages.displayString_bs_D, RegExMessages.additionalInfo_bs_D); //$NON-NLS-1$
104
addBsProposal("\\s", RegExMessages.displayString_bs_s, RegExMessages.additionalInfo_bs_s); //$NON-NLS-1$
105
addBsProposal("\\S", RegExMessages.displayString_bs_S, RegExMessages.additionalInfo_bs_S); //$NON-NLS-1$
106
addBsProposal("\\w", RegExMessages.displayString_bs_w, RegExMessages.additionalInfo_bs_w); //$NON-NLS-1$
107
addBsProposal("\\W", RegExMessages.displayString_bs_W, RegExMessages.additionalInfo_bs_W); //$NON-NLS-1$
108

109             // back reference
110
addBsProposal("\\", RegExMessages.displayString_bs_i, RegExMessages.additionalInfo_bs_i); //$NON-NLS-1$
111

112             //quoting
113
addBsProposal("\\", RegExMessages.displayString_bs, RegExMessages.additionalInfo_bs); //$NON-NLS-1$
114
addBsProposal("\\Q", RegExMessages.displayString_bs_Q, RegExMessages.additionalInfo_bs_Q); //$NON-NLS-1$
115
addBsProposal("\\E", RegExMessages.displayString_bs_E, RegExMessages.additionalInfo_bs_E); //$NON-NLS-1$
116

117             //character sets
118
if (! fIsEscape) {
119                 addBracketProposal("[]", 1, RegExMessages.displayString_set, RegExMessages.additionalInfo_set); //$NON-NLS-1$
120
addBracketProposal("[^]", 2, RegExMessages.displayString_setExcl, RegExMessages.additionalInfo_setExcl); //$NON-NLS-1$
121
addBracketProposal("[-]", 1, RegExMessages.displayString_setRange, RegExMessages.additionalInfo_setRange); //$NON-NLS-1$
122
addProposal("&&", RegExMessages.displayString_setInter, RegExMessages.additionalInfo_setInter); //$NON-NLS-1$
123
}
124             if (! fIsEscape && fDocumentOffset > 0 && fExpression.charAt(fDocumentOffset - 1) == '\\') {
125                 addProposal("\\p{}", 3, RegExMessages.displayString_posix, RegExMessages.additionalInfo_posix); //$NON-NLS-1$
126
addProposal("\\P{}", 3, RegExMessages.displayString_posixNot, RegExMessages.additionalInfo_posixNot); //$NON-NLS-1$
127
} else {
128                 addBracketProposal("\\p{}", 3, RegExMessages.displayString_posix, RegExMessages.additionalInfo_posix); //$NON-NLS-1$
129
addBracketProposal("\\P{}", 3, RegExMessages.displayString_posixNot, RegExMessages.additionalInfo_posixNot); //$NON-NLS-1$
130
}
131             
132 // addBsProposal("\\p{Lower}", RegExMessages.displayString_bs_p{Lower}, RegExMessages.additionalInfo_bs_p{Lower}); //$NON-NLS-1$
133
// addBsProposal("\\p{Upper}", RegExMessages.displayString_bs_p{Upper}, RegExMessages.additionalInfo_bs_p{Upper}); //$NON-NLS-1$
134
// addBsProposal("\\p{ASCII}", RegExMessages.displayString_bs_p{ASCII}, RegExMessages.additionalInfo_bs_p{ASCII}); //$NON-NLS-1$
135
// addBsProposal("\\p{Alpha}", RegExMessages.displayString_bs_p{Alpha}, RegExMessages.additionalInfo_bs_p{Alpha}); //$NON-NLS-1$
136
// addBsProposal("\\p{Digit}", RegExMessages.displayString_bs_p{Digit}, RegExMessages.additionalInfo_bs_p{Digit}); //$NON-NLS-1$
137
// addBsProposal("\\p{Alnum}", RegExMessages.displayString_bs_p{Alnum}, RegExMessages.additionalInfo_bs_p{Alnum}); //$NON-NLS-1$
138
// addBsProposal("\\p{Punct}", RegExMessages.displayString_bs_p{Punct}, RegExMessages.additionalInfo_bs_p{Punct}); //$NON-NLS-1$
139
// addBsProposal("\\p{Graph}", RegExMessages.displayString_bs_p{Graph}, RegExMessages.additionalInfo_bs_p{Graph}); //$NON-NLS-1$
140
// addBsProposal("\\p{Print}", RegExMessages.displayString_bs_p{Print}, RegExMessages.additionalInfo_bs_p{Print}); //$NON-NLS-1$
141
// addBsProposal("\\p{Blank}", RegExMessages.displayString_bs_p{Blank}, RegExMessages.additionalInfo_bs_p{Blank}); //$NON-NLS-1$
142
// addBsProposal("\\p{Cntrl}", RegExMessages.displayString_bs_p{Cntrl}, RegExMessages.additionalInfo_bs_p{Cntrl}); //$NON-NLS-1$
143
// addBsProposal("\\p{XDigit}", RegExMessages.displayString_bs_p{XDigit}, RegExMessages.additionalInfo_bs_p{XDigit}); //$NON-NLS-1$
144
// addBsProposal("\\p{Space}", RegExMessages.displayString_bs_p{Space}, RegExMessages.additionalInfo_bs_p{Space}); //$NON-NLS-1$
145
//
146
// addBsProposal("\\p{InGreek}", RegExMessages.displayString_bs_p{InGreek}, RegExMessages.additionalInfo_bs_p{InGreek}); //$NON-NLS-1$
147
// addBsProposal("\\p{Lu}", RegExMessages.displayString_bs_p{Lu}, RegExMessages.additionalInfo_bs_p{Lu}); //$NON-NLS-1$
148
// addBsProposal("\\p{Sc}", RegExMessages.displayString_bs_p{Sc}, RegExMessages.additionalInfo_bs_p{Sc}); //$NON-NLS-1$
149
// addBsProposal("\\P{InGreek}", RegExMessages.displayString_bs_P{InGreek}, RegExMessages.additionalInfo_bs_P{InGreek}); //$NON-NLS-1$
150

151             //boundary matchers
152
if (fDocumentOffset == 0) {
153                 addPriorityProposal("^", RegExMessages.displayString_start, RegExMessages.additionalInfo_start); //$NON-NLS-1$
154
} else if (fDocumentOffset == 1 && fExpression.charAt(0) == '^') {
155                 addBracketProposal("^", 1, RegExMessages.displayString_start, RegExMessages.additionalInfo_start); //$NON-NLS-1$
156
}
157             if (fDocumentOffset == fExpression.length()) {
158                 addProposal("$", RegExMessages.displayString_end, RegExMessages.additionalInfo_end); //$NON-NLS-1$
159
}
160             addBsProposal("\\b", RegExMessages.displayString_bs_b, RegExMessages.additionalInfo_bs_b); //$NON-NLS-1$
161
addBsProposal("\\B", RegExMessages.displayString_bs_B, RegExMessages.additionalInfo_bs_B); //$NON-NLS-1$
162
addBsProposal("\\A", RegExMessages.displayString_bs_A, RegExMessages.additionalInfo_bs_A); //$NON-NLS-1$
163
addBsProposal("\\G", RegExMessages.displayString_bs_G, RegExMessages.additionalInfo_bs_G); //$NON-NLS-1$
164
addBsProposal("\\Z", RegExMessages.displayString_bs_Z, RegExMessages.additionalInfo_bs_Z); //$NON-NLS-1$
165
addBsProposal("\\z", RegExMessages.displayString_bs_z, RegExMessages.additionalInfo_bs_z); //$NON-NLS-1$
166

167             if (! fIsEscape) {
168                 //capturing groups
169
addBracketProposal("()", 1, RegExMessages.displayString_group, RegExMessages.additionalInfo_group); //$NON-NLS-1$
170

171                 //flags
172
addBracketProposal("(?)", 2, RegExMessages.displayString_flag, RegExMessages.additionalInfo_flag); //$NON-NLS-1$
173
addBracketProposal("(?:)", 3, RegExMessages.displayString_flagExpr, RegExMessages.additionalInfo_flagExpr); //$NON-NLS-1$
174

175                 //non-capturing group
176
addBracketProposal("(?:)", 3, RegExMessages.displayString_nonCap, RegExMessages.additionalInfo_nonCap); //$NON-NLS-1$
177
addBracketProposal("(?>)", 3, RegExMessages.displayString_atomicCap, RegExMessages.additionalInfo_atomicCap); //$NON-NLS-1$
178

179                 //lookaraound
180
addBracketProposal("(?=)", 3, RegExMessages.displayString_posLookahead, RegExMessages.additionalInfo_posLookahead); //$NON-NLS-1$
181
addBracketProposal("(?!)", 3, RegExMessages.displayString_negLookahead, RegExMessages.additionalInfo_negLookahead); //$NON-NLS-1$
182
addBracketProposal("(?<=)", 4, RegExMessages.displayString_posLookbehind, RegExMessages.additionalInfo_posLookbehind); //$NON-NLS-1$
183
addBracketProposal("(?<!)", 4, RegExMessages.displayString_negLookbehind, RegExMessages.additionalInfo_negLookbehind); //$NON-NLS-1$
184

185                 //greedy quantifiers
186
addBracketProposal("?", 1, RegExMessages.displayString_quest, RegExMessages.additionalInfo_quest); //$NON-NLS-1$
187
addBracketProposal("*", 1, RegExMessages.displayString_star, RegExMessages.additionalInfo_star); //$NON-NLS-1$
188
addBracketProposal("+", 1, RegExMessages.displayString_plus, RegExMessages.additionalInfo_plus); //$NON-NLS-1$
189
addBracketProposal("{}", 1, RegExMessages.displayString_exact, RegExMessages.additionalInfo_exact); //$NON-NLS-1$
190
addBracketProposal("{,}", 1, RegExMessages.displayString_least, RegExMessages.additionalInfo_least); //$NON-NLS-1$
191
addBracketProposal("{,}", 1, RegExMessages.displayString_count, RegExMessages.additionalInfo_count); //$NON-NLS-1$
192

193                 //lazy quantifiers
194
addBracketProposal("??", 1, RegExMessages.displayString_questLazy, RegExMessages.additionalInfo_questLazy); //$NON-NLS-1$
195
addBracketProposal("*?", 1, RegExMessages.displayString_starLazy, RegExMessages.additionalInfo_starLazy); //$NON-NLS-1$
196
addBracketProposal("+?", 1, RegExMessages.displayString_plusLazy, RegExMessages.additionalInfo_plusLazy); //$NON-NLS-1$
197
addBracketProposal("{}?", 1, RegExMessages.displayString_exactLazy, RegExMessages.additionalInfo_exactLazy); //$NON-NLS-1$
198
addBracketProposal("{,}?", 1, RegExMessages.displayString_leastLazy, RegExMessages.additionalInfo_leastLazy); //$NON-NLS-1$
199
addBracketProposal("{,}?", 1, RegExMessages.displayString_countLazy, RegExMessages.additionalInfo_countLazy); //$NON-NLS-1$
200

201                 //possessive quantifiers
202
addBracketProposal("?+", 1, RegExMessages.displayString_questPoss, RegExMessages.additionalInfo_questPoss); //$NON-NLS-1$
203
addBracketProposal("*+", 1, RegExMessages.displayString_starPoss, RegExMessages.additionalInfo_starPoss); //$NON-NLS-1$
204
addBracketProposal("++", 1, RegExMessages.displayString_plusPoss, RegExMessages.additionalInfo_plusPoss); //$NON-NLS-1$
205
addBracketProposal("{}+", 1, RegExMessages.displayString_exactPoss, RegExMessages.additionalInfo_exactPoss); //$NON-NLS-1$
206
addBracketProposal("{,}+", 1, RegExMessages.displayString_leastPoss, RegExMessages.additionalInfo_leastPoss); //$NON-NLS-1$
207
addBracketProposal("{,}+", 1, RegExMessages.displayString_countPoss, RegExMessages.additionalInfo_countPoss); //$NON-NLS-1$
208

209                 //alternative
210
addBracketProposal("|", 1, RegExMessages.displayString_alt, RegExMessages.additionalInfo_alt); //$NON-NLS-1$
211
}
212             
213             fPriorityProposals.addAll(fProposals);
214             return (ICompletionProposal[]) fPriorityProposals.toArray(new ICompletionProposal[fProposals.size()]);
215         }
216
217         /**
218          * Computes applicable proposals for the replace field.
219          * @return the proposals
220          */

221         public ICompletionProposal[] computeReplaceProposals() {
222             if (fDocumentOffset > 0 && '$' == fExpression.charAt(fDocumentOffset - 1)) {
223                 addProposal("", RegExMessages.displayString_dollar, RegExMessages.additionalInfo_dollar); //$NON-NLS-1$
224
} else {
225                 addProposal("$", RegExMessages.displayString_dollar, RegExMessages.additionalInfo_dollar); //$NON-NLS-1$
226
addBsProposal("\\", RegExMessages.displayString_replace_bs, RegExMessages.additionalInfo_replace_bs); //$NON-NLS-1$
227
addProposal("\t", RegExMessages.displayString_tab, RegExMessages.additionalInfo_tab); //$NON-NLS-1$
228
}
229             return (ICompletionProposal[]) fProposals.toArray(new ICompletionProposal[fProposals.size()]);
230         }
231         
232         /**
233          * Adds a proposal.
234          *
235          * @param proposal the string to be inserted
236          * @param displayString the proposal's label
237          * @param additionalInfo the additional information
238          */

239         private void addProposal(String JavaDoc proposal, String JavaDoc displayString, String JavaDoc additionalInfo) {
240             fProposals.add(new CompletionProposal(proposal, fDocumentOffset, 0, proposal.length(), null, displayString, null, additionalInfo));
241         }
242
243         /**
244          * Adds a proposal.
245          *
246          * @param proposal the string to be inserted
247          * @param cursorPosition the cursor position after insertion,
248          * relative to the start of the proposal
249          * @param displayString the proposal's label
250          * @param additionalInfo the additional information
251          */

252         private void addProposal(String JavaDoc proposal, int cursorPosition, String JavaDoc displayString, String JavaDoc additionalInfo) {
253             fProposals.add(new CompletionProposal(proposal, fDocumentOffset, 0, cursorPosition, null, displayString, null, additionalInfo));
254         }
255
256         /**
257          * Adds a proposal to the priority proposals list.
258          *
259          * @param proposal the string to be inserted
260          * @param displayString the proposal's label
261          * @param additionalInfo the additional information
262          */

263         private void addPriorityProposal(String JavaDoc proposal, String JavaDoc displayString, String JavaDoc additionalInfo) {
264             fPriorityProposals.add(new CompletionProposal(proposal, fDocumentOffset, 0, proposal.length(), null, displayString, null, additionalInfo));
265         }
266         
267         /**
268          * Adds a proposal. Ensures that existing pre- and postfixes are not duplicated.
269          *
270          * @param proposal the string to be inserted
271          * @param cursorPosition the cursor position after insertion,
272          * relative to the start of the proposal
273          * @param displayString the proposal's label
274          * @param additionalInfo the additional information
275          */

276         private void addBracketProposal(String JavaDoc proposal, int cursorPosition, String JavaDoc displayString, String JavaDoc additionalInfo) {
277             String JavaDoc prolog= fExpression.substring(0, fDocumentOffset);
278             if (! fIsEscape && prolog.endsWith("\\") && proposal.startsWith("\\")) { //$NON-NLS-1$//$NON-NLS-2$
279
fProposals.add(new CompletionProposal(proposal, fDocumentOffset, 0, cursorPosition, null, displayString, null, additionalInfo));
280                 return;
281             }
282             for (int i= 1; i <= cursorPosition; i++) {
283                 String JavaDoc prefix= proposal.substring(0, i);
284                 if (prolog.endsWith(prefix)) {
285                     String JavaDoc postfix= proposal.substring(cursorPosition);
286                     String JavaDoc epilog= fExpression.substring(fDocumentOffset);
287                     if (epilog.startsWith(postfix)) {
288                         fPriorityProposals.add(new CompletionProposal(proposal.substring(i, cursorPosition), fDocumentOffset, 0, cursorPosition - i, null, displayString, null, additionalInfo));
289                     } else {
290                         fPriorityProposals.add(new CompletionProposal(proposal.substring(i), fDocumentOffset, 0, cursorPosition - i, null, displayString, null, additionalInfo));
291                     }
292                     return;
293                 }
294             }
295             fProposals.add(new CompletionProposal(proposal, fDocumentOffset, 0, cursorPosition, null, displayString, null, additionalInfo));
296         }
297
298         /**
299          * Adds a proposal that starts with a backslash.
300          *
301          * @param proposal the string to be inserted
302          * @param displayString the proposal's label
303          * @param additionalInfo the additional information
304          */

305         private void addBsProposal(String JavaDoc proposal, String JavaDoc displayString, String JavaDoc additionalInfo) {
306             if (fIsEscape) {
307                 fPriorityProposals.add(new CompletionProposal(proposal.substring(1), fDocumentOffset, 0, proposal.length() - 1, null, displayString, null, additionalInfo));
308             } else {
309                 addProposal(proposal, displayString, additionalInfo);
310             }
311         }
312     }
313
314     /**
315      * The context information validator.
316      */

317     private IContextInformationValidator fValidator= new SubjectControlContextInformationValidator(this);
318
319     /**
320      * <code>true</code> iff the processor is for the find field.
321      * <code>false</code> iff the processor is for the replace field.
322      * @since 3.1
323      */

324     private final boolean fIsFind;
325     
326     /*
327      * @since 3.1
328      */

329     public RegExContentAssistProcessor(boolean isFind) {
330         fIsFind= isFind;
331     }
332     
333     /*
334      * @see IContentAssistProcessor#computeCompletionProposals(ITextViewer, int)
335      */

336     public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int documentOffset) {
337         return null;
338     }
339
340     /*
341      * @see IContentAssistProcessor#computeContextInformation(ITextViewer, int)
342      */

343     public IContextInformation[] computeContextInformation(ITextViewer viewer, int documentOffset) {
344         return null;
345     }
346
347     /*
348      * @see IContentAssistProcessor#getCompletionProposalAutoActivationCharacters()
349      */

350     public char[] getCompletionProposalAutoActivationCharacters() {
351         if (fIsFind)
352             return new char[] {'\\', '[', '('};
353         
354         return new char[] {'$'};
355     }
356
357     /*
358      * @see IContentAssistProcessor#getContextInformationAutoActivationCharacters()
359      */

360     public char[] getContextInformationAutoActivationCharacters() {
361         return new char[] { };
362     }
363
364     /*
365      * @see IContentAssistProcessor#getContextInformationValidator()
366      */

367     public IContextInformationValidator getContextInformationValidator() {
368         return fValidator;
369     }
370
371     /*
372      * @see IContentAssistProcessor#getErrorMessage()
373      */

374     public String JavaDoc getErrorMessage() {
375         return null;
376     }
377
378     /*
379      * @see ISubjectControlContentAssistProcessor#computeCompletionProposals(IContentAssistSubjectControl, int)
380      */

381     public ICompletionProposal[] computeCompletionProposals(IContentAssistSubjectControl contentAssistSubjectControl, int documentOffset) {
382         if (fIsFind)
383             return new ProposalComputer(contentAssistSubjectControl, documentOffset).computeFindProposals();
384         
385         return new ProposalComputer(contentAssistSubjectControl, documentOffset).computeReplaceProposals();
386     }
387
388     /*
389      * @see ISubjectControlContentAssistProcessor#computeContextInformation(IContentAssistSubjectControl, int)
390      */

391     public IContextInformation[] computeContextInformation(IContentAssistSubjectControl contentAssistSubjectControl, int documentOffset) {
392         return null;
393     }
394 }
395
Popular Tags