1 19 package org.netbeans.modules.languages; 20 21 import java.lang.ref.WeakReference ; 22 import java.util.Iterator ; 23 import java.util.List ; 24 import java.util.Map ; 25 import java.util.ArrayList ; 26 import javax.swing.JEditorPane ; 27 import javax.swing.SwingUtilities ; 28 import javax.swing.event.DocumentEvent ; 29 import javax.swing.event.DocumentListener ; 30 import javax.swing.text.Document ; 31 import org.netbeans.api.languages.ASTEvaluator; 32 import org.netbeans.api.languages.ASTEvaluator; 33 import org.netbeans.api.languages.ASTItem; 34 import org.netbeans.api.languages.ASTPath; 35 import org.netbeans.api.languages.LanguagesManager; 36 import org.netbeans.api.languages.ParserManager; 37 import org.netbeans.api.languages.ParserManagerListener; 38 import org.netbeans.api.languages.ASTToken; 39 import org.netbeans.api.languages.SyntaxContext; 40 import org.netbeans.api.languages.ParseException; 41 import org.netbeans.api.lexer.Token; 42 import org.netbeans.api.lexer.TokenHierarchy; 43 import org.netbeans.api.lexer.TokenSequence; 44 import org.netbeans.api.languages.SyntaxContext; 45 import org.netbeans.api.languages.ASTNode; 46 import org.netbeans.modules.languages.parser.TokenInput; 47 import org.netbeans.modules.languages.LanguagesManagerImpl; 48 import org.netbeans.modules.languages.LanguagesManagerImpl.LanguagesManagerListener; 49 import org.netbeans.modules.languages.parser.LLSyntaxAnalyser; 50 import org.netbeans.modules.editor.NbEditorDocument; 51 import org.openide.cookies.EditorCookie; 52 import org.openide.util.RequestProcessor; 53 import org.openide.ErrorManager; 54 import org.openide.windows.TopComponent; 55 56 57 61 public class ParserManagerImpl extends ParserManager { 62 63 private Document doc; 64 private ASTNode ast = null; 65 private ParseException exception = null; 66 private State state = State.NOT_PARSED; 67 private List <ParserManagerListener> listeners = new ArrayList <ParserManagerListener> (); 68 private List <ASTEvaluator> evaluators = new ArrayList <ASTEvaluator> (); 69 private static RequestProcessor rp = new RequestProcessor ("Parser"); 70 71 72 public ParserManagerImpl (Document doc) { 73 this.doc = doc; 74 new DocListener (this, doc); 75 String mimeType = (String ) doc.getProperty ("mimeType"); 76 } 77 78 public State getState () { 79 return state; 80 } 81 82 public ASTNode getAST () throws ParseException { 83 if (exception != null) throw exception; 84 return ast; 85 } 86 87 public void addListener (ParserManagerListener l) { 88 listeners.add (l); 89 } 90 91 public void removeListener (ParserManagerListener l) { 92 listeners.remove (l); 93 } 94 95 public void addASTEvaluator (ASTEvaluator e) { 96 evaluators.add (e); 97 } 98 99 public void removeASTEvaluator (ASTEvaluator e) { 100 evaluators.remove (e); 101 } 102 103 104 106 private RequestProcessor.Task parsingTask; 107 108 private synchronized void startParsing () { 109 setChange (State.PARSING, ast); 110 if (parsingTask != null) { 111 String mimeType = (String ) doc.getProperty ("mimeType"); 112 try { 113 Language l = ((LanguagesManagerImpl) LanguagesManager.getDefault ()). 114 getLanguage (mimeType); 115 LLSyntaxAnalyser a = l.getAnalyser (); 116 a.cancel (); 117 } catch (ParseException ex) { 118 ex.printStackTrace(); 119 } 120 parsingTask.cancel (); 121 } 122 parsingTask = rp.post (new Runnable () { 123 public void run () { 124 parseAST (); 125 } 126 }, 1000); 127 } 128 129 private void setChange (State state, ASTNode root) { 130 if (state == this.state) return; 131 132 134 this.state = state; 135 this.ast = root; 136 exception = null; 137 Iterator <ParserManagerListener> it = new ArrayList <ParserManagerListener> (listeners).iterator (); 138 while (it.hasNext ()) { 139 ParserManagerListener l = it.next (); 140 l.parsed (state, root); 141 } 142 if (state == State.PARSING) return; 143 if (!evaluators.isEmpty ()) { 144 Iterator <ASTEvaluator> it2 = evaluators.iterator (); 145 while (it2.hasNext ()) { 146 ASTEvaluator e = it2.next (); 147 e.beforeEvaluation (state, root); 148 } 149 evaluate (state, root, root, new ArrayList <ASTItem> ()); 150 it2 = evaluators.iterator (); 151 while (it2.hasNext ()) { 152 ASTEvaluator e = it2.next (); 153 e.afterEvaluation (state, root); 154 } 155 } 156 refreshPanes (); 157 } 158 159 private void evaluate (State state, ASTItem root, ASTItem item, List <ASTItem> path) { 160 path.add (item); 161 ASTPath path2 = ASTPath.create (path); 162 Iterator <ASTEvaluator> it = evaluators.iterator (); 163 while (it.hasNext ()) { 164 ASTEvaluator e = it.next (); 165 e.evaluate (state, path2); 166 } 167 Iterator <ASTItem> it2 = item.getChildren ().iterator (); 168 while (it2.hasNext ()) 169 evaluate (state, root, it2.next (), path); 170 path.remove (path.size () - 1); 171 } 172 173 private void setChange (ParseException ex) { 174 state = State.ERROR; 175 ast = null; 176 exception = ex; 177 Iterator <ParserManagerListener> it = new ArrayList <ParserManagerListener> (listeners).iterator (); 178 while (it.hasNext ()) { 179 ParserManagerListener l = it.next (); 180 l.parsed (state, ast); 181 } 182 if (state == State.PARSING) return; 183 refreshPanes(); 184 } 185 186 private void refreshPanes() { 187 SwingUtilities.invokeLater(new Runnable () { 188 public void run() { 189 Iterator it = TopComponent.getRegistry ().getOpened ().iterator (); 190 while (it.hasNext ()) { 191 TopComponent tc = (TopComponent) it.next (); 192 EditorCookie ec = (EditorCookie) tc.getLookup ().lookup (EditorCookie.class); 193 if (ec == null) continue; 194 JEditorPane [] eps = ec.getOpenedPanes (); 195 if (eps == null) { 196 continue; 197 } 198 int i, k = eps.length; 199 for (i = 0; i < k; i++) { 200 if (eps[i].getDocument () == doc) { 201 eps[i].repaint (); 202 } 203 } 204 } 205 } 206 }); 207 } 208 209 private void parseAST () { 210 try { 211 setChange (State.PARSING, ast); 212 ast = parse (doc); 213 if (ast == null) { 214 setChange (new ParseException ("ast is null?!")); 215 return; 216 } 217 ast = process (ast); 218 if (ast == null) { 219 setChange (new ParseException ("ast is null?!")); 220 return; 221 } 222 setChange (State.OK, ast); 223 } catch (ParseException ex) { 224 if (ex.getASTNode () != null) { 225 ASTNode ast = process (ex.getASTNode ()); 226 ex = new ParseException (ex, ast); 227 } 228 setChange (ex); 229 ErrorManager.getDefault ().notify (ex); 230 } 231 } 232 233 private ASTNode process (ASTNode root) { 234 try { 235 String mimeType = (String ) doc.getProperty ("mimeType"); 236 Language l = ((LanguagesManagerImpl) LanguagesManager.getDefault ()). 237 getLanguage (mimeType); 238 Feature astProperties = l.getFeature ("AST"); 239 if (astProperties != null && ast != null) { 240 return (ASTNode) astProperties.getValue ( 241 "process", 242 SyntaxContext.create (doc, ASTPath.create (root)) 243 ); 244 } 245 return root; 246 } catch (Exception ex) { 247 ErrorManager.getDefault ().notify (ex); 248 return root; 249 } 250 } 251 252 private static ASTNode parse (Document doc) throws ParseException { 253 String mimeType = (String ) doc.getProperty ("mimeType"); 254 Language l = ((LanguagesManagerImpl) LanguagesManager.getDefault ()). 255 getLanguage (mimeType); 256 LLSyntaxAnalyser a = l.getAnalyser (); 257 long start = System.currentTimeMillis (); 258 259 TokenInput input = createTokenInput (doc); 260 long to = System.currentTimeMillis () - start; 261 ASTNode n = a.read (input, true); 262 System.out.println("parse " + doc.getProperty ("title") + " " + (System.currentTimeMillis () - start) + " " + to); 263 return n; 264 } 265 266 private static TokenInput createTokenInput (Document doc) { 267 try { 268 if (doc instanceof NbEditorDocument) 269 ((NbEditorDocument) doc).readLock (); 270 TokenHierarchy th = TokenHierarchy.get (doc); 271 TokenSequence ts = th.tokenSequence (); 272 return TokenInput.create (getTokens (ts)); 273 } finally { 274 if (doc instanceof NbEditorDocument) 275 ((NbEditorDocument) doc).readUnlock (); 276 } 277 } 278 279 private static List <ASTToken> getTokens (TokenSequence ts) { 280 List <ASTToken> tokens = new ArrayList <ASTToken> (); 281 while (ts.moveNext ()) { 282 Token t = ts.token (); 283 String type = t.id ().name (); 284 int offset = ts.offset (); 285 String ttype = (String ) t.getProperty ("type"); 286 if (ttype == null || ttype.equals ("E")) { 287 List <ASTToken> children = null; 288 TokenSequence ts2 = ts.embedded (); 289 if (ts2 != null) 290 children = getTokens (ts2); 291 tokens.add (ASTToken.create ( 292 ts.language ().mimeType (), 293 type, 294 t.text ().toString (), 295 offset, 296 t.length (), 297 children 298 )); 299 } else 300 if (ttype.equals ("S")) { 301 StringBuilder sb = new StringBuilder (t.text ().toString ()); 302 List <ASTToken> children = new ArrayList <ASTToken> (); 303 TokenSequence ts2 = ts.embedded (); 304 while (ts.moveNext ()) { 309 t = ts.token (); 310 ttype = (String ) t.getProperty ("type"); 311 if (ttype == null) { 312 ts.movePrevious (); 313 break; 314 } 315 if (ttype.equals ("E")) { 316 ts2 = ts.embedded (); 317 children.addAll ( 326 getTokens (ts2) 327 ); 328 continue; 329 } 330 if (ttype.equals ("S")) { 331 ts.movePrevious (); 332 break; 333 } 334 if (!ttype.equals ("C")) 335 throw new IllegalArgumentException (); 336 if (!type.equals (t.id ().name ())) 342 throw new IllegalArgumentException (); 343 sb.append (t.text ().toString ()); 344 } 345 int no = ts.offset () + ts.token ().length (); 346 tokens.add (ASTToken.create ( 347 ts.language ().mimeType (), 348 type, 349 sb.toString (), 350 offset, 351 no - offset, 352 children 353 )); 354 } else 355 throw new IllegalArgumentException (); 356 } 357 return tokens; 358 } 359 360 361 363 private static class DocListener implements DocumentListener , 364 LanguagesManagerListener { 365 366 private WeakReference <ParserManagerImpl> pmwr; 367 private ParserManagerImpl pman; 368 369 DocListener (ParserManagerImpl pm, Document doc) { 370 pmwr = new WeakReference <ParserManagerImpl> (pm); 371 pman = pm; 372 doc.addDocumentListener (this); 373 ((LanguagesManagerImpl) LanguagesManager.getDefault ()).addLanguagesManagerListener (this); 374 } 375 376 private ParserManagerImpl getPM () { 377 ParserManagerImpl pm = pmwr.get (); 378 pman = null; 379 if (pm != null) return pm; 380 ((LanguagesManagerImpl) LanguagesManager.getDefault ()).removeLanguagesManagerListener (this); 381 return null; 382 } 383 384 public void insertUpdate (DocumentEvent e) { 385 ParserManagerImpl pm = getPM (); 386 if (pm == null) return; 387 pm.startParsing (); 388 } 389 390 public void removeUpdate (DocumentEvent e) { 391 ParserManagerImpl pm = getPM (); 392 if (pm == null) return; 393 pm.startParsing (); 394 } 395 396 public void changedUpdate (DocumentEvent e) { 397 getPM (); 398 } 399 400 public void languageChanged (String mimeType) { 401 ParserManagerImpl pm = getPM (); 402 if (pm == null) return; 403 pm.startParsing (); 404 } 405 406 public void languageAdded(String mimeType) { 407 getPM (); 408 } 409 410 public void languageRemoved(String mimeType) { 411 getPM (); 412 } 413 } 414 } 415 416 417 418 | Popular Tags |