1 19 20 package org.netbeans.editor; 21 22 import java.io.File ; 23 import java.io.IOException ; 24 import java.beans.PropertyChangeEvent ; 25 import java.util.HashMap ; 26 import javax.swing.text.BadLocationException ; 27 import javax.swing.text.Segment ; 28 29 35 36 public class SyntaxSupport { 37 38 private static final int[] EMPTY_INT_ARRAY = new int[0]; 39 40 private static final int MATCH_ARRAY_CACHE_SIZE = 3; 41 42 private HashMap supMap; 43 44 45 private BaseDocument doc; 46 47 55 protected boolean tokenNumericIDsValid; 56 57 private int[] tokenBlocks = EMPTY_INT_ARRAY; 58 59 private TokenID[][] lastTokenIDArrays = new TokenID[MATCH_ARRAY_CACHE_SIZE][]; 60 61 private boolean[][] lastMatchArrays = new boolean[MATCH_ARRAY_CACHE_SIZE][]; 62 63 public SyntaxSupport(BaseDocument doc) { 64 this.doc = doc; 65 66 } 67 68 69 public final BaseDocument getDocument() { 70 return doc; 71 } 72 73 82 public synchronized SyntaxSupport get(Class syntaxSupportClass) { 83 if (supMap == null) { 84 supMap = new HashMap (11); 85 } 86 87 SyntaxSupport sup = (SyntaxSupport)supMap.get(syntaxSupportClass); 88 if (sup == null) { 89 sup = createSyntaxSupport(syntaxSupportClass); 90 supMap.put(syntaxSupportClass, sup); 91 } 92 93 return sup; 94 } 95 96 protected SyntaxSupport createSyntaxSupport(Class syntaxSupportClass) { 97 if (syntaxSupportClass.isInstance(this)) { 98 return this; 99 } 100 return null; 101 } 102 103 104 107 private boolean[] getMatchArray(TokenID[] tokenIDArray) { 108 boolean[] matchArray = null; 109 int ind; 110 for (ind = 0; ind < MATCH_ARRAY_CACHE_SIZE; ind++) { 111 if (tokenIDArray == lastTokenIDArrays[ind]) { 114 matchArray = lastMatchArrays[ind]; 115 break; 116 } 117 } 118 119 if (matchArray == null) { int maxTokenNumericID = -1; 121 if (tokenIDArray != null) { 122 for (int i = 0; i < tokenIDArray.length; i++) { 123 if (tokenIDArray[i].getNumericID() > maxTokenNumericID) { 124 maxTokenNumericID = tokenIDArray[i].getNumericID(); 125 } 126 } 127 } 128 129 matchArray = new boolean[maxTokenNumericID + 1]; 130 for (int i = 0; i < tokenIDArray.length; i++) { 131 matchArray[tokenIDArray[i].getNumericID()] = true; 132 } 133 } 134 135 if (ind > 0) { 136 ind = Math.min(ind, MATCH_ARRAY_CACHE_SIZE - 1); 137 System.arraycopy(lastTokenIDArrays, 0, lastTokenIDArrays, 1, ind); 138 System.arraycopy(lastMatchArrays, 0, lastMatchArrays, 1, ind); 139 lastTokenIDArrays[0] = tokenIDArray; 140 lastMatchArrays[0] = matchArray; 141 } 142 143 return matchArray; 144 } 145 146 154 public int[] getTokenBlocks(int startPos, int endPos, 155 TokenID[] tokenIDArray) throws BadLocationException { 156 doc.readLock(); 157 try { 158 synchronized (this) { 159 boolean matchArray[] = tokenNumericIDsValid ? getMatchArray(tokenIDArray) : null; 160 int blkInd = 0; 161 if (startPos > endPos) { int tmp = startPos; 163 startPos = endPos; 164 endPos = tmp; 165 } 166 167 SyntaxSeg.Slot slot = SyntaxSeg.getFreeSlot(); 168 Syntax syntax = doc.getFreeSyntax(); 169 try { 170 doc.prepareSyntax(slot, syntax, startPos, endPos - startPos, true, false); 171 172 int preScan = syntax.getPreScan(); 173 int pos = startPos - preScan; 174 int blkStart = -1; 175 176 boolean cont = true; 177 while (cont) { 178 TokenID tokenID = syntax.nextToken(); 179 if (tokenID == null) { 180 cont = false; 181 } else { 182 boolean matches = (tokenID != null) 184 && !(pos + syntax.getTokenLength() <= startPos); 185 if (matches) { 186 if (matchArray != null) { 187 int numID = tokenID.getNumericID(); 188 matches = (numID < matchArray.length && matchArray[numID]); 189 } else { matches = false; 191 for (int i = 0; i < tokenIDArray.length; i++) { 192 if (tokenID == tokenIDArray[i]) { 193 matches = true; 194 break; 195 } 196 } 197 } 198 } 199 200 if (matches) { 201 if (blkStart >= 0) { 202 } else { 204 blkStart = Math.max(pos, startPos); 205 } 206 } else { if (blkStart >= 0) { 208 tokenBlocks = addTokenBlock(tokenBlocks, blkInd, blkStart, pos); 209 blkInd += 2; 210 blkStart = -1; 211 } else { 212 } 214 } 215 pos += syntax.getTokenLength(); 216 } 217 } 218 219 if (blkStart >= 0) { tokenBlocks = addTokenBlock(tokenBlocks, blkInd, blkStart, endPos); 221 blkInd += 2; 222 } 223 224 } finally { 225 doc.releaseSyntax(syntax); 226 SyntaxSeg.releaseSlot(slot); 227 } 228 229 int[] ret = new int[blkInd]; 230 System.arraycopy(tokenBlocks, 0, ret, 0, blkInd); 231 return ret; 232 } 233 } finally { 234 doc.readUnlock(); 235 } 236 } 237 238 private int[] addTokenBlock(int[] blks, int blkInd, int blkStartPos, int blkEndPos) { 239 if (blks.length < blkInd + 2) { 240 int[] tmp = new int[Math.max(2, blks.length * 2)]; 241 System.arraycopy(blks, 0, tmp, 0, blkInd); 242 blks = tmp; 243 } 244 245 blks[blkInd++] = blkStartPos; 246 blks[blkInd] = blkEndPos; 247 return blks; 248 } 249 250 public int findInsideBlocks(Finder finder, 251 int startPos, int endPos, int[] blocks) throws BadLocationException { 252 boolean fwd = (startPos <= endPos); 253 254 if (fwd) { 255 for (int i = 0; i < blocks.length; i += 2) { 256 int pos = doc.find(finder, blocks[i], blocks[i + 1]); 257 if (pos >= 0) { 258 return pos; 259 } 260 } 261 } else { for (int i = blocks.length - 2; i >= 0; i -= 2) { 263 int pos = doc.find(finder, blocks[i + 1], blocks[i]); 264 if (pos >= 0) { 265 return pos; 266 } 267 } 268 } 269 return -1; 270 } 271 272 public int findOutsideBlocks(Finder finder, 273 int startPos, int endPos, int[] blocks) throws BadLocationException { 274 boolean fwd = (startPos <= endPos); 275 276 if (fwd) { 277 int pos = doc.find(finder, startPos, (blocks.length > 0) ? blocks[0] : endPos); 278 if (pos >= 0) { 279 return pos; 280 } 281 282 int ind = 2; 283 while (ind <= blocks.length) { 284 pos = doc.find(finder, blocks[ind - 1], (ind >= blocks.length) ? endPos : blocks[ind]); 285 if (pos >= 0) { 286 return pos; 287 } 288 ind += 2; 289 } 290 } else { int pos = doc.find(finder, startPos, (blocks.length > 0) ? blocks[blocks.length - 1] : endPos); 292 if (pos >= 0) { 293 return pos; 294 } 295 296 int ind = blocks.length - 2; 297 while (ind >= 0) { 298 pos = doc.find(finder, blocks[ind], (ind == 0) ? endPos : blocks[ind - 1]); 299 if (pos >= 0) { 300 return pos; 301 } 302 ind -= 2; 303 } 304 } 305 return -1; 306 } 307 308 319 public void initSyntax(Syntax syntax, int startPos, int endPos, 320 boolean forceLastBuffer, boolean forceNotLastBuffer) 321 throws BadLocationException { 322 doc.readLock(); 323 try { 324 Segment text = DocumentUtilities.SEGMENT_CACHE.getSegment(); 325 try { 326 int docLen = doc.getLength(); 327 doc.prepareSyntax(text, syntax, startPos, 0, forceLastBuffer, forceNotLastBuffer); 328 int preScan = syntax.getPreScan(); 329 char[] buffer = doc.getChars(startPos - preScan, endPos - startPos + preScan); 330 boolean lastBuffer = forceNotLastBuffer ? false 331 : (forceLastBuffer || (endPos == docLen)); 332 syntax.relocate(buffer, preScan, endPos - startPos, lastBuffer, endPos); 333 } finally { 334 DocumentUtilities.SEGMENT_CACHE.releaseSegment(text); 335 } 336 } finally { 337 doc.readUnlock(); 338 } 339 } 340 341 342 public boolean isIdentifier(String word) { 343 if (word == null || word.length() == 0) { 344 return false; } 346 347 for (int i = 0; i < word.length(); i++) { 348 if (!doc.isIdentifierPart(word.charAt(i))) { 349 return false; 350 } 351 } 352 return true; 353 } 354 355 362 public void tokenizeText(TokenProcessor tp, int startOffset, int endOffset, 363 boolean forceLastBuffer) throws BadLocationException { 364 Syntax syntax = null; 365 doc.readLock(); 366 try { 367 Segment text = DocumentUtilities.SEGMENT_CACHE.getSegment(); 368 try { 369 syntax = doc.getFreeSyntax(); 370 int docLen = doc.getLength(); 371 doc.prepareSyntax(text, syntax, startOffset, 372 endOffset - startOffset, forceLastBuffer, false); 373 int preScan = syntax.getPreScan(); 374 tp.nextBuffer(text.array, syntax.getOffset(), endOffset - startOffset, 375 startOffset, preScan, syntax.lastBuffer); 376 377 int bufferStartOffset = startOffset - syntax.getOffset(); 378 379 boolean cont = true; 380 while (cont) { 381 TokenID tokenID = syntax.nextToken(); 382 TokenContextPath tcp = syntax.getTokenContextPath(); 383 if (tokenID == null) { int nextLen = tp.eot(syntax.tokenOffset); 385 nextLen = Math.min(nextLen, docLen - endOffset); 386 if (nextLen == 0) { 387 cont = false; 388 } else { preScan = syntax.getPreScan(); 390 doc.getText(endOffset - preScan, preScan + nextLen, text); 391 392 boolean lastBuffer = forceLastBuffer || (endOffset + nextLen >= docLen); 393 syntax.relocate(text.array, text.offset + preScan, nextLen, 394 lastBuffer, endOffset + nextLen); 395 tp.nextBuffer(text.array, syntax.getOffset(), nextLen, 396 endOffset, preScan, lastBuffer); 397 bufferStartOffset = endOffset - syntax.getOffset(); 398 endOffset += nextLen; 399 } 400 401 } else { int tokenLen = syntax.getTokenLength(); 403 int tokenOffset = syntax.getTokenOffset(); 404 405 if (bufferStartOffset + tokenOffset + tokenLen > startOffset ) { 407 if (!tp.token(tokenID, tcp, tokenOffset, tokenLen)) { 408 cont = false; 409 } 410 } 411 } 412 } 413 } finally { 414 DocumentUtilities.SEGMENT_CACHE.releaseSegment(text); 415 } 416 } finally { 417 if (syntax != null) { 418 doc.releaseSyntax(syntax); 419 } 420 doc.readUnlock(); 421 } 422 } 423 424 428 public void tokenizeText(TokenProcessor tp, String text) { 429 Syntax syntax = null; 430 try { 431 syntax = doc.getFreeSyntax(); 432 char[] buf = text.toCharArray(); 433 syntax.load(null, buf, 0, buf.length, true, -1); 434 435 boolean cont = true; 436 while (cont) { 437 TokenID tokenID = syntax.nextToken(); 438 TokenContextPath tcp = syntax.getTokenContextPath(); 439 if (tokenID == null) { 440 tp.eot(syntax.tokenOffset); 441 cont = false; 442 443 } else { 444 if (!tp.token(tokenID, tcp, syntax.getTokenOffset(), syntax.getTokenLength())) { 445 cont = false; 446 } 447 } 448 } 449 450 } finally { 451 if (syntax != null) { 452 doc.releaseSyntax(syntax); 453 } 454 } 455 } 456 457 458 464 public TokenItem getTokenChain(int offset) throws BadLocationException { 465 if (doc.getLength() <= offset) { 467 return null; 468 } 469 470 return null; 471 } 472 473 481 protected boolean isAbbrevDisabled(int offset) { 482 return false; 483 } 484 485 } 486 | Popular Tags |