1 12 13 package org.eclipse.jdt.internal.ui.text.java; 14 15 16 import java.util.ArrayList ; 17 import java.util.Iterator ; 18 import java.util.List ; 19 20 import org.eclipse.core.runtime.Assert; 21 22 import org.eclipse.jface.preference.IPreferenceStore; 23 import org.eclipse.jface.util.PropertyChangeEvent; 24 25 import org.eclipse.jface.text.rules.ICharacterScanner; 26 import org.eclipse.jface.text.rules.IRule; 27 import org.eclipse.jface.text.rules.IToken; 28 import org.eclipse.jface.text.rules.IWhitespaceDetector; 29 import org.eclipse.jface.text.rules.IWordDetector; 30 import org.eclipse.jface.text.rules.SingleLineRule; 31 import org.eclipse.jface.text.rules.Token; 32 import org.eclipse.jface.text.rules.WhitespaceRule; 33 34 import org.eclipse.jdt.core.JavaCore; 35 36 import org.eclipse.jdt.ui.PreferenceConstants; 37 import org.eclipse.jdt.ui.text.IColorManager; 38 import org.eclipse.jdt.ui.text.IJavaColorConstants; 39 40 import org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlightings; 41 import org.eclipse.jdt.internal.ui.text.AbstractJavaScanner; 42 import org.eclipse.jdt.internal.ui.text.CombinedWordRule; 43 import org.eclipse.jdt.internal.ui.text.JavaWhitespaceDetector; 44 import org.eclipse.jdt.internal.ui.text.JavaWordDetector; 45 import org.eclipse.jdt.internal.ui.text.ISourceVersionDependent; 46 47 48 51 public final class JavaCodeScanner extends AbstractJavaScanner { 52 53 58 private static final class OperatorRule implements IRule { 59 60 61 private final char[] JAVA_OPERATORS= { ';', '.', '=', '/', '\\', '+', '-', '*', '<', '>', ':', '?', '!', ',', '|', '&', '^', '%', '~'}; 62 63 private final IToken fToken; 64 65 70 public OperatorRule(IToken token) { 71 fToken= token; 72 } 73 74 80 public boolean isOperator(char character) { 81 for (int index= 0; index < JAVA_OPERATORS.length; index++) { 82 if (JAVA_OPERATORS[index] == character) 83 return true; 84 } 85 return false; 86 } 87 88 91 public IToken evaluate(ICharacterScanner scanner) { 92 93 int character= scanner.read(); 94 if (isOperator((char) character)) { 95 do { 96 character= scanner.read(); 97 } while (isOperator((char) character)); 98 scanner.unread(); 99 return fToken; 100 } else { 101 scanner.unread(); 102 return Token.UNDEFINED; 103 } 104 } 105 } 106 107 112 private static final class BracketRule implements IRule { 113 114 115 private final char[] JAVA_BRACKETS= { '(', ')', '{', '}', '[', ']' }; 116 117 private final IToken fToken; 118 119 124 public BracketRule(IToken token) { 125 fToken= token; 126 } 127 128 134 public boolean isBracket(char character) { 135 for (int index= 0; index < JAVA_BRACKETS.length; index++) { 136 if (JAVA_BRACKETS[index] == character) 137 return true; 138 } 139 return false; 140 } 141 142 145 public IToken evaluate(ICharacterScanner scanner) { 146 147 int character= scanner.read(); 148 if (isBracket((char) character)) { 149 do { 150 character= scanner.read(); 151 } while (isBracket((char) character)); 152 scanner.unread(); 153 return fToken; 154 } else { 155 scanner.unread(); 156 return Token.UNDEFINED; 157 } 158 } 159 } 160 161 162 private static class VersionedWordMatcher extends CombinedWordRule.WordMatcher implements ISourceVersionDependent { 163 164 private final IToken fDefaultToken; 165 private final String fVersion; 166 private boolean fIsVersionMatch; 167 168 public VersionedWordMatcher(IToken defaultToken, String version, String currentVersion) { 169 fDefaultToken= defaultToken; 170 fVersion= version; 171 setSourceVersion(currentVersion); 172 } 173 174 177 public void setSourceVersion(String version) { 178 fIsVersionMatch= fVersion.compareTo(version) <= 0; 179 } 180 181 184 public IToken evaluate(ICharacterScanner scanner, CombinedWordRule.CharacterBuffer word) { 185 IToken token= super.evaluate(scanner, word); 186 187 if (fIsVersionMatch || token.isUndefined()) 188 return token; 189 190 return fDefaultToken; 191 } 192 } 193 194 203 private static class AnnotationRule implements IRule, ISourceVersionDependent { 204 208 private static final class ResettableScanner implements ICharacterScanner { 209 private final ICharacterScanner fDelegate; 210 private int fReadCount; 211 212 218 public ResettableScanner(final ICharacterScanner scanner) { 219 Assert.isNotNull(scanner); 220 fDelegate= scanner; 221 mark(); 222 } 223 224 227 public int getColumn() { 228 return fDelegate.getColumn(); 229 } 230 231 234 public char[][] getLegalLineDelimiters() { 235 return fDelegate.getLegalLineDelimiters(); 236 } 237 238 241 public int read() { 242 int ch= fDelegate.read(); 243 if (ch != ICharacterScanner.EOF) 244 fReadCount++; 245 return ch; 246 } 247 248 251 public void unread() { 252 if (fReadCount > 0) 253 fReadCount--; 254 fDelegate.unread(); 255 } 256 257 260 public void mark() { 261 fReadCount= 0; 262 } 263 264 267 public void reset() { 268 while (fReadCount > 0) 269 unread(); 270 271 while (fReadCount < 0) 272 read(); 273 } 274 } 275 276 private final IWhitespaceDetector fWhitespaceDetector= new JavaWhitespaceDetector(); 277 private final IWordDetector fWordDetector= new JavaWordDetector(); 278 private final IToken fInterfaceToken; 279 private final IToken fAtToken; 280 private final String fVersion; 281 private boolean fIsVersionMatch; 282 283 295 public AnnotationRule(IToken interfaceToken, Token atToken, String version, String currentVersion) { 296 fInterfaceToken= interfaceToken; 297 fAtToken= atToken; 298 fVersion= version; 299 setSourceVersion(currentVersion); 300 } 301 302 305 public IToken evaluate(ICharacterScanner scanner) { 306 if (!fIsVersionMatch) 307 return Token.UNDEFINED; 308 309 ResettableScanner resettable= new ResettableScanner(scanner); 310 if (resettable.read() == '@') 311 return readAnnotation(resettable); 312 313 resettable.reset(); 314 return Token.UNDEFINED; 315 } 316 317 private IToken readAnnotation(ResettableScanner scanner) { 318 scanner.mark(); 319 skipWhitespace(scanner); 320 if (readInterface(scanner)) { 321 return fInterfaceToken; 322 } else { 323 scanner.reset(); 324 return fAtToken; 325 } 326 } 327 328 private boolean readInterface(ICharacterScanner scanner) { 329 int ch= scanner.read(); 330 int i= 0; 331 while (i < INTERFACE.length() && INTERFACE.charAt(i) == ch) { 332 i++; 333 ch= scanner.read(); 334 } 335 if (i < INTERFACE.length()) 336 return false; 337 338 if (fWordDetector.isWordPart((char) ch)) 339 return false; 340 341 if (ch != ICharacterScanner.EOF) 342 scanner.unread(); 343 344 return true; 345 } 346 347 private boolean skipWhitespace(ICharacterScanner scanner) { 348 while (fWhitespaceDetector.isWhitespace((char) scanner.read())) { 349 } 351 352 scanner.unread(); 353 return true; 354 } 355 356 359 public void setSourceVersion(String version) { 360 fIsVersionMatch= fVersion.compareTo(version) <= 0; 361 } 362 363 } 364 365 private static final String SOURCE_VERSION= JavaCore.COMPILER_SOURCE; 366 367 static String [] fgKeywords= { 368 "abstract", "break", "case", "catch", "class", "const", "continue", "default", "do", "else", "extends", "final", "finally", "for", "goto", "if", "implements", "import", "instanceof", "interface", "native", "new", "package", "private", "protected", "public", "static", "super", "switch", "synchronized", "this", "throw", "throws", "transient", "try", "volatile", "while" }; 383 384 private static final String INTERFACE= "interface"; private static final String RETURN= "return"; private static String [] fgJava14Keywords= { "assert" }; private static String [] fgJava15Keywords= { "enum" }; 389 private static String [] fgTypes= { "void", "boolean", "char", "byte", "short", "strictfp", "int", "long", "float", "double" }; 391 private static String [] fgConstants= { "false", "null", "true" }; 393 private static final String ANNOTATION_BASE_KEY= PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_PREFIX + SemanticHighlightings.ANNOTATION; 394 private static final String ANNOTATION_COLOR_KEY= ANNOTATION_BASE_KEY + PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_COLOR_SUFFIX; 395 396 private static String [] fgTokenProperties= { 397 IJavaColorConstants.JAVA_KEYWORD, 398 IJavaColorConstants.JAVA_STRING, 399 IJavaColorConstants.JAVA_DEFAULT, 400 IJavaColorConstants.JAVA_KEYWORD_RETURN, 401 IJavaColorConstants.JAVA_OPERATOR, 402 IJavaColorConstants.JAVA_BRACKET, 403 ANNOTATION_COLOR_KEY, 404 }; 405 406 private List fVersionDependentRules= new ArrayList (3); 407 408 414 public JavaCodeScanner(IColorManager manager, IPreferenceStore store) { 415 super(manager, store); 416 initialize(); 417 } 418 419 422 protected String [] getTokenProperties() { 423 return fgTokenProperties; 424 } 425 426 429 protected List createRules() { 430 431 List rules= new ArrayList (); 432 433 Token token= getToken(IJavaColorConstants.JAVA_STRING); 435 rules.add(new SingleLineRule("'", "'", token, '\\')); 437 438 rules.add(new WhitespaceRule(new JavaWhitespaceDetector())); 440 441 String version= getPreferenceStore().getString(SOURCE_VERSION); 442 443 token= getToken(ANNOTATION_COLOR_KEY); 445 AnnotationRule atInterfaceRule= new AnnotationRule(getToken(IJavaColorConstants.JAVA_KEYWORD), token, JavaCore.VERSION_1_5, version); 446 rules.add(atInterfaceRule); 447 fVersionDependentRules.add(atInterfaceRule); 448 449 JavaWordDetector wordDetector= new JavaWordDetector(); 451 token= getToken(IJavaColorConstants.JAVA_DEFAULT); 452 CombinedWordRule combinedWordRule= new CombinedWordRule(wordDetector, token); 453 454 token= getToken(IJavaColorConstants.JAVA_DEFAULT); 455 VersionedWordMatcher j14Matcher= new VersionedWordMatcher(token, JavaCore.VERSION_1_4, version); 456 457 token= getToken(IJavaColorConstants.JAVA_KEYWORD); 458 for (int i=0; i<fgJava14Keywords.length; i++) 459 j14Matcher.addWord(fgJava14Keywords[i], token); 460 461 combinedWordRule.addWordMatcher(j14Matcher); 462 fVersionDependentRules.add(j14Matcher); 463 464 token= getToken(IJavaColorConstants.JAVA_DEFAULT); 465 VersionedWordMatcher j15Matcher= new VersionedWordMatcher(token, JavaCore.VERSION_1_5, version); 466 token= getToken(IJavaColorConstants.JAVA_KEYWORD); 467 for (int i=0; i<fgJava15Keywords.length; i++) 468 j15Matcher.addWord(fgJava15Keywords[i], token); 469 470 combinedWordRule.addWordMatcher(j15Matcher); 471 fVersionDependentRules.add(j15Matcher); 472 473 token= getToken(IJavaColorConstants.JAVA_OPERATOR); 475 rules.add(new OperatorRule(token)); 476 477 token= getToken(IJavaColorConstants.JAVA_BRACKET); 479 rules.add(new BracketRule(token)); 480 481 CombinedWordRule.WordMatcher returnWordRule= new CombinedWordRule.WordMatcher(); 483 token= getToken(IJavaColorConstants.JAVA_KEYWORD_RETURN); 484 returnWordRule.addWord(RETURN, token); 485 combinedWordRule.addWordMatcher(returnWordRule); 486 487 CombinedWordRule.WordMatcher wordRule= new CombinedWordRule.WordMatcher(); 489 token= getToken(IJavaColorConstants.JAVA_KEYWORD); 490 for (int i=0; i<fgKeywords.length; i++) 491 wordRule.addWord(fgKeywords[i], token); 492 for (int i=0; i<fgTypes.length; i++) 493 wordRule.addWord(fgTypes[i], token); 494 for (int i=0; i<fgConstants.length; i++) 495 wordRule.addWord(fgConstants[i], token); 496 497 combinedWordRule.addWordMatcher(wordRule); 498 499 rules.add(combinedWordRule); 500 501 setDefaultReturnToken(getToken(IJavaColorConstants.JAVA_DEFAULT)); 502 return rules; 503 } 504 505 508 protected String getBoldKey(String colorKey) { 509 if ((ANNOTATION_COLOR_KEY).equals(colorKey)) 510 return ANNOTATION_BASE_KEY + PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_BOLD_SUFFIX; 511 return super.getBoldKey(colorKey); 512 } 513 514 517 protected String getItalicKey(String colorKey) { 518 if ((ANNOTATION_COLOR_KEY).equals(colorKey)) 519 return ANNOTATION_BASE_KEY + PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_ITALIC_SUFFIX; 520 return super.getItalicKey(colorKey); 521 } 522 523 526 protected String getStrikethroughKey(String colorKey) { 527 if ((ANNOTATION_COLOR_KEY).equals(colorKey)) 528 return ANNOTATION_BASE_KEY + PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_STRIKETHROUGH_SUFFIX; 529 return super.getStrikethroughKey(colorKey); 530 } 531 532 535 protected String getUnderlineKey(String colorKey) { 536 if ((ANNOTATION_COLOR_KEY).equals(colorKey)) 537 return ANNOTATION_BASE_KEY + PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_UNDERLINE_SUFFIX; 538 return super.getUnderlineKey(colorKey); 539 } 540 541 544 public boolean affectsBehavior(PropertyChangeEvent event) { 545 return event.getProperty().equals(SOURCE_VERSION) || super.affectsBehavior(event); 546 } 547 548 551 public void adaptToPreferenceChange(PropertyChangeEvent event) { 552 553 if (event.getProperty().equals(SOURCE_VERSION)) { 554 Object value= event.getNewValue(); 555 556 if (value instanceof String ) { 557 String s= (String ) value; 558 559 for (Iterator it= fVersionDependentRules.iterator(); it.hasNext();) { 560 ISourceVersionDependent dependent= (ISourceVersionDependent) it.next(); 561 dependent.setSourceVersion(s); 562 } 563 } 564 565 } else if (super.affectsBehavior(event)) { 566 super.adaptToPreferenceChange(event); 567 } 568 } 569 } 570 | Popular Tags |