1 11 package org.eclipse.jdt.internal.ui.text; 12 13 import com.ibm.icu.text.BreakIterator; 14 import java.text.CharacterIterator ; 15 16 import org.eclipse.core.runtime.Assert; 17 18 19 20 29 public class JavaBreakIterator extends BreakIterator { 30 31 34 protected static abstract class Run { 35 36 protected int length; 37 38 public Run() { 39 init(); 40 } 41 42 50 protected boolean consume(char ch) { 51 if (isValid(ch)) { 52 length++; 53 return true; 54 } 55 return false; 56 } 57 58 65 protected abstract boolean isValid(char ch); 66 67 70 protected void init() { 71 length= 0; 72 } 73 } 74 75 static final class Whitespace extends Run { 76 protected boolean isValid(char ch) { 77 return Character.isWhitespace(ch) && ch != '\n' && ch != '\r'; 78 } 79 } 80 81 static final class LineDelimiter extends Run { 82 83 private char fState; 84 private static final char INIT= '\0'; 85 private static final char EXIT= '\1'; 86 87 90 protected void init() { 91 super.init(); 92 fState= INIT; 93 } 94 95 98 protected boolean consume(char ch) { 99 if (!isValid(ch) || fState == EXIT) 100 return false; 101 102 if (fState == INIT) { 103 fState= ch; 104 length++; 105 return true; 106 } else if (fState != ch) { 107 fState= EXIT; 108 length++; 109 return true; 110 } else { 111 return false; 112 } 113 } 114 115 protected boolean isValid(char ch) { 116 return ch == '\n' || ch == '\r'; 117 } 118 } 119 120 static final class Identifier extends Run { 121 124 protected boolean isValid(char ch) { 125 return Character.isJavaIdentifierPart(ch); 126 } 127 } 128 129 static final class CamelCaseIdentifier extends Run { 130 131 private static final int S_INIT= 0; 132 private static final int S_LOWER= 1; 133 private static final int S_ONE_CAP= 2; 134 private static final int S_ALL_CAPS= 3; 135 private static final int S_EXIT= 4; 136 private static final int S_EXIT_MINUS_ONE= 5; 137 138 139 private static final int K_INVALID= 0; 140 private static final int K_LOWER= 1; 141 private static final int K_UPPER= 2; 142 private static final int K_OTHER= 3; 143 144 private int fState; 145 146 private final static int[][] MATRIX= new int[][] { 147 { S_EXIT, S_LOWER, S_ONE_CAP, S_LOWER }, { S_EXIT, S_LOWER, S_EXIT, S_LOWER }, { S_EXIT, S_LOWER, S_ALL_CAPS, S_LOWER }, { S_EXIT, S_EXIT_MINUS_ONE, S_ALL_CAPS, S_LOWER }, }; 153 154 157 protected void init() { 158 super.init(); 159 fState= S_INIT; 160 } 161 162 165 protected boolean consume(char ch) { 166 int kind= getKind(ch); 167 fState= MATRIX[fState][kind]; 168 switch (fState) { 169 case S_LOWER: 170 case S_ONE_CAP: 171 case S_ALL_CAPS: 172 length++; 173 return true; 174 case S_EXIT: 175 return false; 176 case S_EXIT_MINUS_ONE: 177 length--; 178 return false; 179 default: 180 Assert.isTrue(false); 181 return false; 182 } 183 } 184 185 190 private int getKind(char ch) { 191 if (Character.isUpperCase(ch)) 192 return K_UPPER; 193 if (Character.isLowerCase(ch)) 194 return K_LOWER; 195 if (Character.isJavaIdentifierPart(ch)) return K_OTHER; 197 return K_INVALID; 198 } 199 200 203 protected boolean isValid(char ch) { 204 return Character.isJavaIdentifierPart(ch); 205 } 206 } 207 208 static final class Other extends Run { 209 212 protected boolean isValid(char ch) { 213 return !Character.isWhitespace(ch) && !Character.isJavaIdentifierPart(ch); 214 } 215 } 216 217 private static final Run WHITESPACE= new Whitespace(); 218 private static final Run DELIMITER= new LineDelimiter(); 219 private static final Run CAMELCASE= new CamelCaseIdentifier(); private static final Run OTHER= new Other(); 221 222 223 protected final BreakIterator fIterator; 224 225 protected CharSequence fText; 226 227 private int fIndex; 228 229 230 233 public JavaBreakIterator() { 234 fIterator= BreakIterator.getWordInstance(); 235 fIndex= fIterator.current(); 236 } 237 238 241 public int current() { 242 return fIndex; 243 } 244 245 248 public int first() { 249 fIndex= fIterator.first(); 250 return fIndex; 251 } 252 253 256 public int following(int offset) { 257 if (offset == getText().getEndIndex()) 259 return DONE; 260 261 int next= fIterator.following(offset); 262 if (next == DONE) 263 return DONE; 264 265 Run run= consumeRun(offset); 270 return offset + run.length; 271 272 } 273 274 279 private Run consumeRun(int offset) { 280 282 char ch= fText.charAt(offset); 283 int length= fText.length(); 284 Run run= getRun(ch); 285 while (run.consume(ch) && offset < length - 1) { 286 offset++; 287 ch= fText.charAt(offset); 288 } 289 290 return run; 291 } 292 293 299 private Run getRun(char ch) { 300 Run run; 301 if (WHITESPACE.isValid(ch)) 302 run= WHITESPACE; 303 else if (DELIMITER.isValid(ch)) 304 run= DELIMITER; 305 else if (CAMELCASE.isValid(ch)) 306 run= CAMELCASE; 307 else if (OTHER.isValid(ch)) 308 run= OTHER; 309 else { 310 Assert.isTrue(false); 311 return null; 312 } 313 314 run.init(); 315 return run; 316 } 317 318 321 public CharacterIterator getText() { 322 return fIterator.getText(); 323 } 324 325 328 public boolean isBoundary(int offset) { 329 if (offset == getText().getBeginIndex()) 330 return true; 331 else 332 return following(offset - 1) == offset; 333 } 334 335 338 public int last() { 339 fIndex= fIterator.last(); 340 return fIndex; 341 } 342 343 346 public int next() { 347 fIndex= following(fIndex); 348 return fIndex; 349 } 350 351 354 public int next(int n) { 355 return fIterator.next(n); 356 } 357 358 361 public int preceding(int offset) { 362 if (offset == getText().getBeginIndex()) 363 return DONE; 364 365 if (isBoundary(offset - 1)) 366 return offset - 1; 367 368 int previous= offset - 1; 369 do { 370 previous= fIterator.preceding(previous); 371 } while (!isBoundary(previous)); 372 373 int last= DONE; 374 while (previous < offset) { 375 last= previous; 376 previous= following(previous); 377 } 378 379 return last; 380 } 381 382 385 public int previous() { 386 fIndex= preceding(fIndex); 387 return fIndex; 388 } 389 390 393 public void setText(String newText) { 394 setText((CharSequence ) newText); 395 } 396 397 401 public void setText(CharSequence newText) { 402 fText= newText; 403 fIterator.setText(new SequenceCharacterIterator(newText)); 404 first(); 405 } 406 407 410 public void setText(CharacterIterator newText) { 411 if (newText instanceof CharSequence ) { 412 fText= (CharSequence ) newText; 413 fIterator.setText(newText); 414 first(); 415 } else { 416 throw new UnsupportedOperationException ("CharacterIterator not supported"); } 418 } 419 } 420 | Popular Tags |