1 19 20 package org.netbeans.modules.languages.features; 21 22 import java.util.ArrayList ; 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 ; 54 import javax.swing.text.JTextComponent ; 55 import java.util.List ; 56 import java.util.Map ; 57 58 59 63 public class CompletionProviderImpl implements CompletionProvider { 64 65 private static final String COMPLETION = "COMPLETION"; 66 67 68 public CompletionTask createTask (int queryType, JTextComponent component) { 69 return new CompletionTaskImpl (component); 70 } 71 72 public int getAutoQueryTypes (JTextComponent component, String typedText) { 73 return 0; 74 } 75 76 private static class CompletionTaskImpl implements CompletionTask { 77 78 private JTextComponent component; 79 private NbEditorDocument doc; 80 private boolean ignoreCase; 81 private List <CompletionItem> items = new ArrayList <CompletionItem> (); 82 83 84 CompletionTaskImpl (JTextComponent component) { 85 this.component = component; 86 } 87 88 public void query (CompletionResultSet resultSet) { 89 compute (resultSet); 91 } 92 93 public void refresh (CompletionResultSet resultSet) { 94 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 start = token.text ().toString (); 107 start = start.substring (0, offset - tokenSequence.offset ()).trim (); 108 if (start.equals (".")) 109 start = ""; if (ignoreCase) start = start.toLowerCase (); 111 112 Iterator <CompletionItem> it = items.iterator (); 113 while (it.hasNext ()) { 114 CompletionItem item = it.next (); 115 CharSequence chs = item.getInsertPrefix (); 116 String s = chs instanceof String ? (String ) chs : chs.toString (); 117 if (s.startsWith (start)) 118 resultSet.addItem (item); 119 } 120 resultSet.finish (); 121 } 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 mimeType = tokenSequence.language ().mimeType (); 144 Feature feature = null; 145 String 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 return; 157 } 158 start = start.substring (0, offset - tokenSequence.offset ()).trim (); 159 if (start.equals (".")) 160 start = ""; String 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 parserManager.addListener (new ParserManagerListener () { 184 public void parsed (State state, ASTNode ast) { 185 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 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 return; 215 } 216 String start = token.getIdentifier ().substring ( 217 0, offset - token.getOffset () 218 ).trim (); 219 if (start.equals (".")) 220 start = ""; 222 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 start, Context context, CompletionResultSet resultSet) { 241 int j = 1; 242 while (true) { 243 Object o = feature.getValue ("text" + j, context); 244 if (o == null) break; 245 if (o instanceof String ) 246 addTags ((String ) o, feature, j, start, resultSet); 247 else { 248 addMethodCallTags ( 249 (List ) o, 250 context, 251 resultSet, 252 start 253 ); 254 } 255 j++; 256 } } 258 259 262 private void addMethodCallTags ( 263 List keys, 264 Context context, 265 CompletionResultSet resultSet, 266 String start 267 ) { 268 Iterator it = keys.iterator (); 269 while (it.hasNext ()) { 270 Object o = it.next (); 271 if (o instanceof CompletionItem) { 272 CompletionItem item = (CompletionItem) o; 273 items.add (item); 274 CharSequence chs = item.getInsertPrefix (); 275 String s = chs instanceof String ? (String ) chs : chs.toString (); 276 if (ignoreCase) 277 s = s.toLowerCase (); 278 if (s.startsWith (start)) 279 resultSet.addItem (item); 280 } else { 281 String t = (String ) 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 text, 293 Feature feature, 294 int j, 295 String start, 296 CompletionResultSet resultSet 297 ) { 298 if (ignoreCase) 299 text = text.toLowerCase (); 300 String description = (String ) feature.getValue ("description" + j); 301 if (description == null) 302 description = text; 303 String icon = (String ) 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 |