1 19 20 package org.netbeans.modules.languages.features; 21 22 import java.util.ListIterator ; 23 import java.util.ListIterator ; 24 import java.util.StringTokenizer ; 25 import java.util.WeakHashMap ; 26 import java.util.ArrayList ; 27 import java.util.Collection ; 28 import java.util.HashMap ; 29 import java.util.HashSet ; 30 import java.util.Iterator ; 31 import java.util.List ; 32 import java.util.List ; 33 import java.util.Map ; 34 import java.util.Set ; 35 import java.util.WeakHashMap ; 36 import javax.swing.text.Document ; 37 import org.netbeans.api.languages.ASTEvaluator; 38 import org.netbeans.api.languages.ASTItem; 39 import org.netbeans.api.languages.ASTItem; 40 import org.netbeans.api.languages.ASTPath; 41 import org.netbeans.api.languages.ASTToken; 42 import org.netbeans.api.languages.LanguagesManager; 43 import org.netbeans.api.languages.ParseException; 44 import org.netbeans.api.languages.DatabaseManager; 45 import org.netbeans.api.languages.ParserManager; 46 import org.netbeans.api.languages.ParserManager.State; 47 import org.netbeans.api.languages.SyntaxContext; 48 import org.netbeans.modules.editor.NbEditorDocument; 49 import org.netbeans.modules.editor.NbEditorUtilities; 50 import org.netbeans.modules.languages.Feature; 51 import org.netbeans.modules.languages.Language; 52 import org.netbeans.api.languages.SyntaxContext; 53 import org.netbeans.api.languages.ASTNode; 54 import org.netbeans.api.languages.ParseException; 55 import org.netbeans.modules.languages.LanguagesManagerImpl; 56 import org.openide.cookies.LineCookie; 57 import org.openide.loaders.DataObject; 58 import org.openide.text.Line; 59 import org.openide.text.NbDocument; 60 61 62 66 public final class DatabaseManagerImpl extends DatabaseManager { 67 68 private Map <Object ,Map <String ,Object >> contextToId = new WeakHashMap <Object ,Map <String ,Object >> (); 69 private Map <Document ,Object []> documentToContexts = new WeakHashMap <Document ,Object []> (); 70 71 { 72 } 75 76 77 public List <Line.Part> get (ASTPath path, String id, boolean recursive) { 78 List <Line.Part> result = new ArrayList <Line.Part> (); 79 ListIterator <ASTItem> it = path.listIterator (path.size ()); 80 while (it.hasPrevious ()) { 81 ASTItem item = it.previous (); 82 Map idToLines = contextToId.get (item); 83 if (idToLines != null) { 84 Object o = idToLines.get (id); 85 if (o != null) { 86 if (o instanceof Set ) 87 result.addAll ((Set <Line.Part>) o); 88 else 89 result.add ((Line.Part) o); 90 if (!recursive) return result; 91 } 92 } 93 } 94 return result; 95 } 96 97 public List <Line.Part> get (Object context, String id) { 98 List <Line.Part> result = new ArrayList <Line.Part> (); 99 Map idToLines = contextToId.get (context); 100 if (idToLines != null) { 101 Object o = idToLines.get (id); 102 if (o != null) { 103 if (o instanceof Set ) 104 result.addAll ((Set <Line.Part>) o); 105 else 106 result.add ((Line.Part) o); 107 } 108 } 109 return result; 110 } 111 112 public Collection <String > getIds (ASTPath path, boolean recursive) { 113 List <String > result = new ArrayList <String > (); 114 ListIterator <ASTItem> it = path.listIterator (path.size ()); 115 while (it.hasPrevious ()) { 116 ASTItem item = it.previous (); 117 Map <String ,Object > idToLines = contextToId.get (item); 118 if (idToLines != null) { 119 result.addAll (idToLines.keySet ()); 120 if (!recursive) return result; 121 } 122 } 123 return result; 124 } 125 126 public Collection <String > getIds (Object context) { 127 List <String > result = new ArrayList <String > (); 128 Map <String ,Object > idToLines = contextToId.get (context); 129 if (idToLines != null) 130 result.addAll (idToLines.keySet ()); 131 return result; 132 } 133 134 private void removeIDs (Document doc) { 135 Object [] contexts = documentToContexts.remove (doc); 136 if (contexts == null) return; 137 Iterator it = ((Set ) contexts [0]).iterator (); 138 while (it.hasNext ()) { 139 ASTNode node = (ASTNode) it.next (); 140 contextToId.remove (node); 141 } 142 it = ((Map ) contexts [1]).keySet ().iterator (); 143 while (it.hasNext ()) { 144 Object context = it.next (); 145 Map idToLinesTBD = (Map ) ((Map ) contexts [1]).get (context); 146 Map idToLines = contextToId.get (context); 147 if (idToLines == null) return; 148 Iterator it2 = idToLinesTBD.keySet ().iterator (); 149 while (it2.hasNext ()) { 150 Object id = it2.next (); 151 Object linesTBD = idToLinesTBD.get (id); 152 Object lines = idToLines.get (id); 153 if (linesTBD instanceof Set ) { 154 if (lines instanceof Set ) { 155 ((Set ) lines).removeAll ((Set ) linesTBD); 156 if (((Set ) lines).isEmpty ()) 157 idToLines.remove (id); 158 } else { 159 if (((Set ) linesTBD).contains (lines)) 160 idToLines.remove (id); 161 } 162 } else 163 if (lines instanceof Set ) { 164 ((Set ) lines).remove (linesTBD); 165 if (((Set ) lines).isEmpty ()) 166 idToLines.remove (id); 167 } else 168 idToLines.remove (id); 169 } 170 } 171 } 172 173 private void addId (Document doc, Object context, String id, Line.Part l) { 174 Map idToLines = contextToId.get (context); 175 if (idToLines == null) { 176 idToLines = new HashMap (); 177 contextToId.put (context, idToLines); 178 } 179 Object lines = idToLines.get (id); 180 if (lines == null) 181 idToLines.put (id, l); 182 else 183 if (lines instanceof Line.Part) { 184 Set list = new HashSet (); 185 list.add (lines); 186 list.add (l); 187 idToLines.put (id, list); 188 } else { 189 ((Set ) lines).add (l); 190 } 191 192 Object [] contexts = documentToContexts.get (doc); 193 if (contexts == null) { 194 contexts = new Object [] {new HashSet (), new HashMap ()}; 195 documentToContexts.put (doc, contexts); 196 } 197 if (context instanceof ASTNode) 198 ((Set ) contexts [0]).add (context); 199 else { 200 idToLines = (Map ) ((Map ) contexts [1]).get (context); 201 if (idToLines == null) { 202 idToLines = new HashMap (); 203 ((Map ) contexts [1]).put (context, idToLines); 204 } 205 Object o = idToLines.get (id); 206 if (o == null) 207 idToLines.put (id, l); 208 else 209 if (o instanceof Set ) 210 ((Set ) o).add (l); 211 else { 212 Set list = new HashSet (); 213 list.add (o); 214 list.add (l); 215 idToLines.put (id, list); 216 } 217 } 218 } 219 220 221 public class Listener extends ASTEvaluator { 222 private NbEditorDocument doc; 223 private ParserManager parser; 224 private Line.Set lineSet; 225 226 227 228 public Listener (Document doc) { 229 this.doc = (NbEditorDocument) doc; 231 parser = ParserManager.get ((NbEditorDocument) doc); 232 parser.addASTEvaluator (this); 233 } 234 235 public void beforeEvaluation (State state, ASTNode root) { 236 removeIDs (doc); 237 DataObject dob = NbEditorUtilities.getDataObject (doc); 238 if (dob == null) return; 239 LineCookie lc = (LineCookie) dob.getCookie (LineCookie.class); 240 lineSet = lc.getLineSet (); 241 } 242 243 public void afterEvaluation (State state, ASTNode root) { 244 lineSet = null; 245 } 246 247 public void evaluate (State state, ASTPath path) { 248 if (lineSet == null) return; 249 ASTItem item = path.getLeaf (); 250 try { 251 Language language = ((LanguagesManagerImpl) LanguagesManager.getDefault ()). 252 getLanguage (item.getMimeType ()); 253 Feature store = language.getFeature (Language.STORE, path); 254 if (store != null) { 255 if (store.getBoolean ("condition", SyntaxContext.create (doc, path), true)) { 256 Object [] contextProperties = (Object []) getContext (store); 257 String defaultContext = (String ) contextProperties [0]; 258 Set contexts = (Set ) contextProperties [1]; 259 ListIterator <ASTItem> it = path.listIterator (path.size ()); 260 Object context = defaultContext; 261 while (it.hasPrevious ()) { 262 ASTItem item2 = it.previous (); 263 if (item2 instanceof ASTToken) 264 continue; 265 ASTNode cn = (ASTNode) item2; 266 if (contexts.contains (cn.getNT ())) { 267 context = cn; 268 break; 269 } 270 } 271 String name = (String ) store.getValue ( 272 "name", 273 SyntaxContext.create (doc, path) 274 ); 275 if (name != null) { 276 int lineNumber = NbDocument.findLineNumber (doc, item.getOffset ()); 277 int column = NbDocument.findLineColumn (doc, item.getOffset ()); 278 Line line = lineSet.getCurrent (lineNumber); 279 Line.Part part = line.createPart (column, 0); 280 addId (doc, context, name, part); 282 } 283 } 284 } 285 } catch (ParseException ex) { 286 } 287 } 288 289 private Map <Feature,Object []> contexts = new WeakHashMap <Feature,Object []> (); 290 291 private Object [] getContext (Feature store) { 292 if (!contexts.containsKey (store)) { 293 String c = (String ) store.getValue ("context"); 294 String first = null; 295 StringTokenizer st = new StringTokenizer (c, ","); 296 Set cs = new HashSet (); 297 while (st.hasMoreElements ()) 298 if (first == null) 299 first = st.nextToken ().trim (); 300 else 301 cs.add (st.nextToken ().trim ()); 302 contexts.put (store, new Object [] {first, cs}); 303 } 304 return contexts.get (store); 305 } 306 } 307 } 308 309 | Popular Tags |