KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > languages > features > CompletionProviderImpl


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.languages.features;
21
22 import java.util.ArrayList JavaDoc;
23 import org.netbeans.api.languages.ASTItem;
24 import org.netbeans.api.languages.LanguagesManager;
25 import org.netbeans.api.languages.LanguagesManager;
26 import org.netbeans.api.languages.ParseException;
27 import org.netbeans.api.languages.ASTPath;
28 import org.netbeans.api.languages.ParserManager;
29 import org.netbeans.api.languages.ParserManager.State;
30 import org.netbeans.api.languages.ParserManagerListener;
31 import org.netbeans.api.languages.ASTToken;
32 import org.netbeans.api.languages.SyntaxContext;
33 import org.netbeans.api.languages.ASTNode;
34 import org.netbeans.api.languages.ParseException;
35 import org.netbeans.api.languages.support.CompletionSupport;
36 import org.netbeans.api.lexer.Token;
37 import org.netbeans.api.lexer.TokenHierarchy;
38 import org.netbeans.api.lexer.TokenSequence;
39 import org.netbeans.api.languages.Context;
40 import org.netbeans.modules.editor.NbEditorDocument;
41 import org.netbeans.modules.languages.Feature;
42 import org.netbeans.modules.languages.Language;
43 import org.netbeans.modules.languages.LanguagesManagerImpl;
44 import org.netbeans.modules.languages.LanguagesManagerImpl;
45 import org.netbeans.modules.languages.ParserManagerImpl;
46 import org.netbeans.spi.editor.completion.CompletionItem;
47 import org.netbeans.spi.editor.completion.CompletionItem;
48 import org.netbeans.spi.editor.completion.CompletionProvider;
49 import org.netbeans.spi.editor.completion.CompletionResultSet;
50 import org.netbeans.spi.editor.completion.CompletionTask;
51 import org.openide.ErrorManager;
52 import org.openide.ErrorManager;
53 import java.util.Iterator JavaDoc;
54 import javax.swing.text.JTextComponent JavaDoc;
55 import java.util.List JavaDoc;
56 import java.util.Map JavaDoc;
57
58
59 /**
60  *
61  * @author Jan Jancura
62  */

63 public class CompletionProviderImpl implements CompletionProvider {
64     
65     private static final String JavaDoc COMPLETION = "COMPLETION";
66     
67     
68     public CompletionTask createTask (int queryType, JTextComponent JavaDoc component) {
69         return new CompletionTaskImpl (component);
70     }
71
72     public int getAutoQueryTypes (JTextComponent JavaDoc component, String JavaDoc typedText) {
73         return 0;
74     }
75     
76     private static class CompletionTaskImpl implements CompletionTask {
77         
78         private JTextComponent JavaDoc component;
79         private NbEditorDocument doc;
80         private boolean ignoreCase;
81         private List JavaDoc<CompletionItem> items = new ArrayList JavaDoc<CompletionItem> ();
82         
83         
84         CompletionTaskImpl (JTextComponent JavaDoc component) {
85             this.component = component;
86         }
87         
88         public void query (CompletionResultSet resultSet) {
89             //S ystem.out.println("CodeCompletion: query " + resultSet);
90
compute (resultSet);
91         }
92
93         public void refresh (CompletionResultSet resultSet) {
94             //S ystem.out.println("CodeCompletion: refresh " + resultSet);
95
if (resultSet == null) return;
96
97             TokenHierarchy tokenHierarchy = TokenHierarchy.get (doc);
98             TokenSequence tokenSequence = tokenHierarchy.tokenSequence ();
99             int offset = component.getCaret ().getDot ();
100             tokenSequence.move (offset - 1);
101             if (!tokenSequence.moveNext() && !tokenSequence.movePrevious()) {
102                 resultSet.finish ();
103                 return;
104             }
105             Token token = tokenSequence.token ();
106             String JavaDoc start = token.text ().toString ();
107             start = start.substring (0, offset - tokenSequence.offset ()).trim ();
108             if (start.equals ("."))
109                 start = "";// [HACK]
110
if (ignoreCase) start = start.toLowerCase ();
111
112             Iterator JavaDoc<CompletionItem> it = items.iterator ();
113             while (it.hasNext ()) {
114                 CompletionItem item = it.next ();
115                 CharSequence JavaDoc chs = item.getInsertPrefix ();
116                 String JavaDoc s = chs instanceof String JavaDoc ? (String JavaDoc) chs : chs.toString ();
117                 if (s.startsWith (start))
118                     resultSet.addItem (item);
119             }
120             resultSet.finish ();
121             //compute (resultSet);
122
}
123
124         public void cancel () {
125         }
126         
127         private void compute (CompletionResultSet resultSet) {
128             doc = (NbEditorDocument) component.getDocument ();
129             TokenHierarchy tokenHierarchy = TokenHierarchy.get (doc);
130             TokenSequence tokenSequence = tokenHierarchy.tokenSequence ();
131             int offset = component.getCaret ().getDot ();
132             compute (tokenSequence, offset, resultSet, doc);
133             addParserTags (resultSet);
134         }
135         
136         private void compute (
137             TokenSequence tokenSequence,
138             int offset,
139             CompletionResultSet resultSet,
140             NbEditorDocument doc
141         ) {
142             if (tokenSequence == null) return;
143             String JavaDoc mimeType = tokenSequence.language ().mimeType ();
144             Feature feature = null;
145             String JavaDoc start = null;
146             try {
147                 Language language = ((LanguagesManagerImpl) LanguagesManager.getDefault ()).
148                     getLanguage (mimeType);
149                 tokenSequence.move (offset - 1);
150                 if (!tokenSequence.moveNext ()) return;
151                 Token token = tokenSequence.token ();
152                 start = token.text ().toString ();
153                 if (tokenSequence.offset () > offset) {
154                     // border of embedded language
155
// [HACK] borders should be represented by some tokens!!!
156
return;
157                 }
158                 start = start.substring (0, offset - tokenSequence.offset ()).trim ();
159                 if (start.equals ("."))
160                     start = "";// [HACK]
161
String JavaDoc tokenType = token.id ().name ();
162                 ignoreCase = false;
163                 Feature f = language.getFeature ("PROPERTIES");
164                 if (f != null)
165                     ignoreCase = f.getBoolean ("ignoreCase", false);
166                 if (ignoreCase) start = start.toLowerCase ();
167                 feature = language.getFeature (
168                     Language.COMPLETION,
169                     tokenType
170                 );
171             } catch (ParseException ex) {
172             }
173             if (feature == null)
174                 compute (tokenSequence.embedded (), offset, resultSet, doc);
175             else
176                 addTags (feature, start, Context.create (doc, tokenSequence), resultSet);
177         }
178
179         private void addParserTags (final CompletionResultSet resultSet) {
180             final ParserManager parserManager = ParserManager.get (doc);
181             if (parserManager.getState () == State.PARSING) {
182                 //S ystem.out.println("CodeCompletion: parsing...");
183
parserManager.addListener (new ParserManagerListener () {
184                     public void parsed (State state, ASTNode ast) {
185                         //S ystem.out.println("CodeCompletion: parsed " + state);
186
addParserTags (ast, resultSet);
187                         resultSet.finish ();
188                         parserManager.removeListener (this);
189                     }
190                 });
191             } else {
192                 try {
193                     addParserTags (ParserManagerImpl.get (doc).getAST (), resultSet);
194                 } catch (ParseException ex) {
195                     ErrorManager.getDefault ().notify (ex);
196                 }
197                 resultSet.finish ();
198             }
199         }
200         
201         private void addParserTags (ASTNode node, CompletionResultSet resultSet) {
202             if (node == null) {
203                 //S ystem.out.println("CodeCompletion: No AST");
204
return;
205             }
206             int offset = component.getCaret ().getDot ();
207             ASTPath path = node.findPath (offset - 1);
208             if (path == null) return;
209             ASTToken token = (ASTToken) path.getLeaf ();
210             if (token.getLength () != token.getIdentifier ().length ()) {
211                 // [HACK]
212
// something like token.getRealIndex () +
213
// add tokens for language borders...
214
return;
215             }
216             String JavaDoc start = token.getIdentifier ().substring (
217                 0, offset - token.getOffset ()
218             ).trim ();
219             if (start.equals ("."))
220                 start = "";// [HACK]
221

222             //S ystem.out.println("CodeCompletion: (syntax) start=" + start + ": stoken=" + token);
223

224             for (int i = path.size () - 1; i >= 0; i--) {
225                 ASTItem item = path.get (i);
226                 try {
227                     Language language = ((LanguagesManagerImpl) LanguagesManager.getDefault ()).
228                         getLanguage (item.getMimeType ());
229                     Feature feature = language.getFeature (COMPLETION, path.subPath (i));
230                     if (feature != null) {
231                         boolean recursive = feature.getBoolean ("recursive", false);
232                         if ((i != path.size () - 1) && !recursive) break;
233                         addTags (feature, start, SyntaxContext.create (doc, path.subPath (i)), resultSet);
234                     }
235                 } catch (ParseException ex) {
236                 }
237             }
238         }
239
240         private void addTags (Feature feature, String JavaDoc start, Context context, CompletionResultSet resultSet) {
241             int j = 1;
242             while (true) {
243                 Object JavaDoc o = feature.getValue ("text" + j, context);
244                 if (o == null) break;
245                 if (o instanceof String JavaDoc)
246                     addTags ((String JavaDoc) o, feature, j, start, resultSet);
247                 else {
248                     addMethodCallTags (
249                         (List JavaDoc) o,
250                         context,
251                         resultSet,
252                         start
253                     );
254                 }
255                 j++;
256             } // while
257
}
258         
259         /**
260          * Adds completion items obtained by method call to result.
261          */

262         private void addMethodCallTags (
263             List JavaDoc keys,
264             Context context,
265             CompletionResultSet resultSet,
266             String JavaDoc start
267         ) {
268             Iterator JavaDoc it = keys.iterator ();
269             while (it.hasNext ()) {
270                 Object JavaDoc o = it.next ();
271                 if (o instanceof CompletionItem) {
272                     CompletionItem item = (CompletionItem) o;
273                     items.add (item);
274                     CharSequence JavaDoc chs = item.getInsertPrefix ();
275                     String JavaDoc s = chs instanceof String JavaDoc ? (String JavaDoc) chs : chs.toString ();
276                     if (ignoreCase)
277                         s = s.toLowerCase ();
278                     if (s.startsWith (start))
279                         resultSet.addItem (item);
280                 } else {
281                     String JavaDoc t = (String JavaDoc) o;
282                     if (ignoreCase) t = t.toLowerCase ();
283                     CompletionItem item = CompletionSupport.createCompletionItem (t);
284                     items.add (item);
285                     if (t.startsWith (start))
286                         resultSet.addItem (item);
287                 }
288             }
289         }
290         
291         private void addTags (
292             String JavaDoc text,
293             Feature feature,
294             int j,
295             String JavaDoc start,
296             CompletionResultSet resultSet
297         ) {
298             if (ignoreCase)
299                 text = text.toLowerCase ();
300             String JavaDoc description = (String JavaDoc) feature.getValue ("description" + j);
301             if (description == null)
302                 description = text;
303             String JavaDoc icon = (String JavaDoc) feature.getValue ("icon" + j);
304             CompletionItem item = CompletionSupport.createCompletionItem (
305                 text, description, icon
306             );
307             items.add (item);
308             if (!text.startsWith (start))
309                 return;
310             resultSet.addItem (item);
311         }
312     }
313 }
Popular Tags