1 11 package org.eclipse.jdt.internal.ui.text; 12 13 14 import org.eclipse.jface.text.IDocument; 15 import org.eclipse.jface.text.rules.ICharacterScanner; 16 import org.eclipse.jface.text.rules.IPartitionTokenScanner; 17 import org.eclipse.jface.text.rules.IToken; 18 import org.eclipse.jface.text.rules.Token; 19 20 import org.eclipse.jdt.ui.text.IJavaPartitions; 21 22 23 27 public class FastJavaPartitionScanner implements IPartitionTokenScanner, IJavaPartitions { 28 29 private static final int JAVA= 0; 31 private static final int SINGLE_LINE_COMMENT= 1; 32 private static final int MULTI_LINE_COMMENT= 2; 33 private static final int JAVADOC= 3; 34 private static final int CHARACTER= 4; 35 private static final int STRING= 5; 36 37 private static final int NONE= 0; 39 private static final int BACKSLASH= 1; private static final int SLASH= 2; private static final int SLASH_STAR= 3; private static final int SLASH_STAR_STAR= 4; private static final int STAR= 5; private static final int CARRIAGE_RETURN=6; 46 47 private final BufferedDocumentScanner fScanner= new BufferedDocumentScanner(1000); 49 50 private int fTokenOffset; 51 52 private int fTokenLength; 53 54 55 private int fState; 56 57 private int fLast; 58 59 private int fPrefixLength; 60 61 private boolean fEmulate= false; 63 private int fJavaOffset; 64 private int fJavaLength; 65 66 private final IToken[] fTokens= new IToken[] { 67 new Token(null), 68 new Token(JAVA_SINGLE_LINE_COMMENT), 69 new Token(JAVA_MULTI_LINE_COMMENT), 70 new Token(JAVA_DOC), 71 new Token(JAVA_CHARACTER), 72 new Token(JAVA_STRING) 73 }; 74 75 public FastJavaPartitionScanner(boolean emulate) { 76 fEmulate= emulate; 77 } 78 79 public FastJavaPartitionScanner() { 80 this(false); 81 } 82 83 86 public IToken nextToken() { 87 88 if (fEmulate) { 90 if (fJavaOffset != -1 && fTokenOffset + fTokenLength != fJavaOffset + fJavaLength) { 91 fTokenOffset += fTokenLength; 92 return fTokens[JAVA]; 93 } else { 94 fJavaOffset= -1; 95 fJavaLength= 0; 96 } 97 } 98 99 fTokenOffset += fTokenLength; 100 fTokenLength= fPrefixLength; 101 102 while (true) { 103 final int ch= fScanner.read(); 104 105 switch (ch) { 107 case ICharacterScanner.EOF: 108 if (fTokenLength > 0) { 109 fLast= NONE; return preFix(fState, JAVA, NONE, 0); 111 112 } else { 113 fLast= NONE; 114 fPrefixLength= 0; 115 return Token.EOF; 116 } 117 118 case '\r': 119 if (!fEmulate && fLast != CARRIAGE_RETURN) { 121 fLast= CARRIAGE_RETURN; 122 fTokenLength++; 123 continue; 124 125 } else { 126 127 switch (fState) { 128 case SINGLE_LINE_COMMENT: 129 case CHARACTER: 130 case STRING: 131 if (fTokenLength > 0) { 132 IToken token= fTokens[fState]; 133 134 if (fEmulate) { 136 fTokenLength++; 137 fLast= NONE; 138 fPrefixLength= 0; 139 } else { 140 fLast= CARRIAGE_RETURN; 141 fPrefixLength= 1; 142 } 143 144 fState= JAVA; 145 return token; 146 147 } else { 148 consume(); 149 continue; 150 } 151 152 default: 153 consume(); 154 continue; 155 } 156 } 157 158 case '\n': 159 switch (fState) { 160 case SINGLE_LINE_COMMENT: 161 case CHARACTER: 162 case STRING: 163 return postFix(fState); 165 166 default: 167 consume(); 168 continue; 169 } 170 171 default: 172 if (!fEmulate && fLast == CARRIAGE_RETURN) { 173 switch (fState) { 174 case SINGLE_LINE_COMMENT: 175 case CHARACTER: 176 case STRING: 177 178 int last; 179 int newState; 180 switch (ch) { 181 case '/': 182 last= SLASH; 183 newState= JAVA; 184 break; 185 186 case '*': 187 last= STAR; 188 newState= JAVA; 189 break; 190 191 case '\'': 192 last= NONE; 193 newState= CHARACTER; 194 break; 195 196 case '"': 197 last= NONE; 198 newState= STRING; 199 break; 200 201 case '\r': 202 last= CARRIAGE_RETURN; 203 newState= JAVA; 204 break; 205 206 case '\\': 207 last= BACKSLASH; 208 newState= JAVA; 209 break; 210 211 default: 212 last= NONE; 213 newState= JAVA; 214 break; 215 } 216 217 fLast= NONE; return preFix(fState, newState, last, 1); 219 220 default: 221 break; 222 } 223 } 224 } 225 226 switch (fState) { 228 case JAVA: 229 switch (ch) { 230 case '/': 231 if (fLast == SLASH) { 232 if (fTokenLength - getLastLength(fLast) > 0) { 233 return preFix(JAVA, SINGLE_LINE_COMMENT, NONE, 2); 234 } else { 235 preFix(JAVA, SINGLE_LINE_COMMENT, NONE, 2); 236 fTokenOffset += fTokenLength; 237 fTokenLength= fPrefixLength; 238 break; 239 } 240 241 } else { 242 fTokenLength++; 243 fLast= SLASH; 244 break; 245 } 246 247 case '*': 248 if (fLast == SLASH) { 249 if (fTokenLength - getLastLength(fLast) > 0) 250 return preFix(JAVA, MULTI_LINE_COMMENT, SLASH_STAR, 2); 251 else { 252 preFix(JAVA, MULTI_LINE_COMMENT, SLASH_STAR, 2); 253 fTokenOffset += fTokenLength; 254 fTokenLength= fPrefixLength; 255 break; 256 } 257 258 } else { 259 consume(); 260 break; 261 } 262 263 case '\'': 264 fLast= NONE; if (fTokenLength > 0) 266 return preFix(JAVA, CHARACTER, NONE, 1); 267 else { 268 preFix(JAVA, CHARACTER, NONE, 1); 269 fTokenOffset += fTokenLength; 270 fTokenLength= fPrefixLength; 271 break; 272 } 273 274 case '"': 275 fLast= NONE; if (fTokenLength > 0) 277 return preFix(JAVA, STRING, NONE, 1); 278 else { 279 preFix(JAVA, STRING, NONE, 1); 280 fTokenOffset += fTokenLength; 281 fTokenLength= fPrefixLength; 282 break; 283 } 284 285 default: 286 consume(); 287 break; 288 } 289 break; 290 291 case SINGLE_LINE_COMMENT: 292 consume(); 293 break; 294 295 case JAVADOC: 296 switch (ch) { 297 case '/': 298 switch (fLast) { 299 case SLASH_STAR_STAR: 300 return postFix(MULTI_LINE_COMMENT); 301 302 case STAR: 303 return postFix(JAVADOC); 304 305 default: 306 consume(); 307 break; 308 } 309 break; 310 311 case '*': 312 fTokenLength++; 313 fLast= STAR; 314 break; 315 316 default: 317 consume(); 318 break; 319 } 320 break; 321 322 case MULTI_LINE_COMMENT: 323 switch (ch) { 324 case '*': 325 if (fLast == SLASH_STAR) { 326 fLast= SLASH_STAR_STAR; 327 fTokenLength++; 328 fState= JAVADOC; 329 } else { 330 fTokenLength++; 331 fLast= STAR; 332 } 333 break; 334 335 case '/': 336 if (fLast == STAR) { 337 return postFix(MULTI_LINE_COMMENT); 338 } else { 339 consume(); 340 break; 341 } 342 343 default: 344 consume(); 345 break; 346 } 347 break; 348 349 case STRING: 350 switch (ch) { 351 case '\\': 352 fLast= (fLast == BACKSLASH) ? NONE : BACKSLASH; 353 fTokenLength++; 354 break; 355 356 case '\"': 357 if (fLast != BACKSLASH) { 358 return postFix(STRING); 359 360 } else { 361 consume(); 362 break; 363 } 364 365 default: 366 consume(); 367 break; 368 } 369 break; 370 371 case CHARACTER: 372 switch (ch) { 373 case '\\': 374 fLast= (fLast == BACKSLASH) ? NONE : BACKSLASH; 375 fTokenLength++; 376 break; 377 378 case '\'': 379 if (fLast != BACKSLASH) { 380 return postFix(CHARACTER); 381 382 } else { 383 consume(); 384 break; 385 } 386 387 default: 388 consume(); 389 break; 390 } 391 break; 392 } 393 } 394 } 395 396 private static final int getLastLength(int last) { 397 switch (last) { 398 default: 399 return -1; 400 401 case NONE: 402 return 0; 403 404 case CARRIAGE_RETURN: 405 case BACKSLASH: 406 case SLASH: 407 case STAR: 408 return 1; 409 410 case SLASH_STAR: 411 return 2; 412 413 case SLASH_STAR_STAR: 414 return 3; 415 } 416 } 417 418 private final void consume() { 419 fTokenLength++; 420 fLast= NONE; 421 } 422 423 private final IToken postFix(int state) { 424 fTokenLength++; 425 fLast= NONE; 426 fState= JAVA; 427 fPrefixLength= 0; 428 return fTokens[state]; 429 } 430 431 private final IToken preFix(int state, int newState, int last, int prefixLength) { 432 if (fEmulate && state == JAVA && (fTokenLength - getLastLength(fLast) > 0)) { 434 fTokenLength -= getLastLength(fLast); 435 fJavaOffset= fTokenOffset; 436 fJavaLength= fTokenLength; 437 fTokenLength= 1; 438 fState= newState; 439 fPrefixLength= prefixLength; 440 fLast= last; 441 return fTokens[state]; 442 443 } else { 444 fTokenLength -= getLastLength(fLast); 445 fLast= last; 446 fPrefixLength= prefixLength; 447 IToken token= fTokens[state]; 448 fState= newState; 449 return token; 450 } 451 } 452 453 private static int getState(String contentType) { 454 455 if (contentType == null) 456 return JAVA; 457 458 else if (contentType.equals(JAVA_SINGLE_LINE_COMMENT)) 459 return SINGLE_LINE_COMMENT; 460 461 else if (contentType.equals(JAVA_MULTI_LINE_COMMENT)) 462 return MULTI_LINE_COMMENT; 463 464 else if (contentType.equals(JAVA_DOC)) 465 return JAVADOC; 466 467 else if (contentType.equals(JAVA_STRING)) 468 return STRING; 469 470 else if (contentType.equals(JAVA_CHARACTER)) 471 return CHARACTER; 472 473 else 474 return JAVA; 475 } 476 477 480 public void setPartialRange(IDocument document, int offset, int length, String contentType, int partitionOffset) { 481 482 fScanner.setRange(document, offset, length); 483 fTokenOffset= partitionOffset; 484 fTokenLength= 0; 485 fPrefixLength= offset - partitionOffset; 486 fLast= NONE; 487 488 if (offset == partitionOffset) { 489 fState= JAVA; 491 } else { 492 fState= getState(contentType); 493 } 494 495 if (fEmulate) { 497 fJavaOffset= -1; 498 fJavaLength= 0; 499 } 500 } 501 502 505 public void setRange(IDocument document, int offset, int length) { 506 507 fScanner.setRange(document, offset, length); 508 fTokenOffset= offset; 509 fTokenLength= 0; 510 fPrefixLength= 0; 511 fLast= NONE; 512 fState= JAVA; 513 514 if (fEmulate) { 516 fJavaOffset= -1; 517 fJavaLength= 0; 518 } 519 } 520 521 524 public int getTokenLength() { 525 return fTokenLength; 526 } 527 528 531 public int getTokenOffset() { 532 return fTokenOffset; 533 } 534 535 } 536 | Popular Tags |