1 11 package org.eclipse.jdt.internal.ui.text.spelling; 12 13 import com.ibm.icu.text.BreakIterator; 14 15 import java.util.LinkedList ; 16 import java.util.Locale ; 17 18 import org.eclipse.jface.text.IDocument; 19 import org.eclipse.jface.text.IRegion; 20 import org.eclipse.jface.text.TextUtilities; 21 22 import org.eclipse.jdt.internal.corext.refactoring.nls.NLSElement; 23 24 import org.eclipse.jdt.internal.ui.text.javadoc.IHtmlTagConstants; 25 import org.eclipse.jdt.internal.ui.text.javadoc.IJavaDocTagConstants; 26 import org.eclipse.jdt.internal.ui.text.spelling.engine.DefaultSpellChecker; 27 import org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellCheckIterator; 28 29 30 35 public class SpellCheckIterator implements ISpellCheckIterator { 36 37 38 protected final String fContent; 39 40 41 private final String fDelimiter; 42 43 44 protected String fLastToken= null; 45 46 47 protected int fNext= 1; 48 49 50 protected final int fOffset; 51 52 53 private int fPredecessor; 54 55 56 protected int fPrevious= 0; 57 58 59 private final LinkedList fSentenceBreaks= new LinkedList (); 60 61 62 private boolean fStartsSentence= false; 63 64 65 protected int fSuccessor; 66 67 68 private final BreakIterator fWordIterator; 69 70 private boolean fIsIgnoringSingleLetters; 71 72 79 public SpellCheckIterator(IDocument document, IRegion region, Locale locale) { 80 this(document, region, locale, BreakIterator.getWordInstance(locale)); 81 } 82 83 91 public SpellCheckIterator(IDocument document, IRegion region, Locale locale, BreakIterator breakIterator) { 92 fOffset= region.getOffset(); 93 fWordIterator= breakIterator; 94 fDelimiter= TextUtilities.getDefaultLineDelimiter(document); 95 96 String content; 97 try { 98 99 content= document.get(region.getOffset(), region.getLength()); 100 if (content.startsWith(NLSElement.TAG_PREFIX)) 101 content= ""; 103 } catch (Exception exception) { 104 content= ""; } 106 fContent= content; 107 108 fWordIterator.setText(content); 109 fPredecessor= fWordIterator.first(); 110 fSuccessor= fWordIterator.next(); 111 112 final BreakIterator iterator= BreakIterator.getSentenceInstance(locale); 113 iterator.setText(content); 114 115 int offset= iterator.current(); 116 while (offset != BreakIterator.DONE) { 117 118 fSentenceBreaks.add(new Integer (offset)); 119 offset= iterator.next(); 120 } 121 } 122 123 127 public void setIgnoreSingleLetters(boolean state) { 128 fIsIgnoringSingleLetters= state; 129 } 130 131 134 public final int getBegin() { 135 return fPrevious + fOffset; 136 } 137 138 141 public final int getEnd() { 142 return fNext + fOffset - 1; 143 } 144 145 148 public final boolean hasNext() { 149 return fSuccessor != BreakIterator.DONE; 150 } 151 152 161 protected final boolean isAlphaNumeric(final int begin, final int end) { 162 163 char character= 0; 164 165 boolean letter= false; 166 for (int index= begin; index < end; index++) { 167 168 character= fContent.charAt(index); 169 if (Character.isLetter(character)) 170 letter= true; 171 172 if (!Character.isLetterOrDigit(character)) 173 return false; 174 } 175 return letter; 176 } 177 178 184 protected final boolean isToken(final String [] tags) { 185 return isToken(fLastToken, tags); 186 } 187 188 196 protected final boolean isToken(final String token, final String [] tags) { 197 198 if (token != null) { 199 200 for (int index= 0; index < tags.length; index++) { 201 202 if (token.equals(tags[index])) 203 return true; 204 } 205 } 206 return false; 207 } 208 209 217 protected final boolean isSingleLetter(final int begin) { 218 if (!Character.isLetter(fContent.charAt(begin))) 219 return false; 220 221 if (begin > 0 && !Character.isWhitespace(fContent.charAt(begin - 1))) 222 return false; 223 224 if (begin < fContent.length() - 1 && !Character.isWhitespace(fContent.charAt(begin + 1))) 225 return false; 226 227 return true; 228 } 229 230 237 protected final boolean isUrlToken(final int begin) { 238 239 for (int index= 0; index < DefaultSpellChecker.URL_PREFIXES.length; index++) { 240 241 if (fContent.startsWith(DefaultSpellChecker.URL_PREFIXES[index], begin)) 242 return true; 243 } 244 return false; 245 } 246 247 255 protected final boolean isWhitespace(final int begin, final int end) { 256 257 for (int index= begin; index < end; index++) { 258 259 if (!Character.isWhitespace(fContent.charAt(index))) 260 return false; 261 } 262 return true; 263 } 264 265 268 public Object next() { 269 270 String token= nextToken(); 271 while (token == null && fSuccessor != BreakIterator.DONE) 272 token= nextToken(); 273 274 fLastToken= token; 275 276 return token; 277 } 278 279 282 protected final void nextBreak() { 283 284 fNext= fSuccessor; 285 fPredecessor= fSuccessor; 286 287 fSuccessor= fWordIterator.next(); 288 } 289 290 295 protected final int nextSentence() { 296 return ((Integer ) fSentenceBreaks.getFirst()).intValue(); 297 } 298 299 305 protected String nextToken() { 306 307 String token= null; 308 309 fPrevious= fPredecessor; 310 fStartsSentence= false; 311 312 nextBreak(); 313 314 boolean update= false; 315 if (fNext - fPrevious > 0) { 316 317 if (fSuccessor != BreakIterator.DONE && fContent.charAt(fPrevious) == IJavaDocTagConstants.JAVADOC_TAG_PREFIX) { 318 319 nextBreak(); 320 if (Character.isLetter(fContent.charAt(fPrevious + 1))) { 321 update= true; 322 token= fContent.substring(fPrevious, fNext); 323 } else 324 fPredecessor= fNext; 325 326 } else if (fSuccessor != BreakIterator.DONE && fContent.charAt(fPrevious) == IHtmlTagConstants.HTML_TAG_PREFIX && (Character.isLetter(fContent.charAt(fNext)) || fContent.charAt(fNext) == '/')) { 327 328 if (fContent.startsWith(IHtmlTagConstants.HTML_CLOSE_PREFIX, fPrevious)) 329 nextBreak(); 330 331 nextBreak(); 332 333 if (fSuccessor != BreakIterator.DONE && fContent.charAt(fNext) == IHtmlTagConstants.HTML_TAG_POSTFIX) { 334 335 nextBreak(); 336 if (fSuccessor != BreakIterator.DONE) { 337 update= true; 338 token= fContent.substring(fPrevious, fNext); 339 } 340 } 341 } else if (fSuccessor != BreakIterator.DONE && fContent.charAt(fPrevious) == IHtmlTagConstants.HTML_ENTITY_START && (Character.isLetter(fContent.charAt(fNext)))) { 342 nextBreak(); 343 if (fSuccessor != BreakIterator.DONE && fContent.charAt(fNext) == IHtmlTagConstants.HTML_ENTITY_END) { 344 nextBreak(); 345 if (isToken(fContent.substring(fPrevious, fNext), IHtmlTagConstants.HTML_ENTITY_CODES)) { 346 skipTokens(fPrevious, IHtmlTagConstants.HTML_ENTITY_END); 347 update= true; 348 } else 349 token= fContent.substring(fPrevious, fNext); 350 } else 351 token= fContent.substring(fPrevious, fNext); 352 353 update= true; 354 } else if (!isWhitespace(fPrevious, fNext) && isAlphaNumeric(fPrevious, fNext)) { 355 356 if (isUrlToken(fPrevious)) 357 skipTokens(fPrevious, ' '); 358 else if (isToken(IJavaDocTagConstants.JAVADOC_PARAM_TAGS)) 359 fLastToken= null; 360 else if (isToken(IJavaDocTagConstants.JAVADOC_REFERENCE_TAGS)) { 361 fLastToken= null; 362 skipTokens(fPrevious, fDelimiter.charAt(0)); 363 } else if (fNext - fPrevious > 1 || isSingleLetter(fPrevious) && !fIsIgnoringSingleLetters) 364 token= fContent.substring(fPrevious, fNext); 365 366 update= true; 367 } 368 } 369 370 if (update && fSentenceBreaks.size() > 0) { 371 372 if (fPrevious >= nextSentence()) { 373 374 while (fSentenceBreaks.size() > 0 && fPrevious >= nextSentence()) 375 fSentenceBreaks.removeFirst(); 376 377 fStartsSentence= (fLastToken == null) || (token != null); 378 } 379 } 380 return token; 381 } 382 383 386 public final void remove() { 387 throw new UnsupportedOperationException (); 388 } 389 390 396 protected final void skipTokens(final int begin, final char stop) { 397 398 int end= begin; 399 400 while (end < fContent.length() && fContent.charAt(end) != stop) 401 end++; 402 403 if (end < fContent.length()) { 404 405 fNext= end; 406 fPredecessor= fNext; 407 408 fSuccessor= fWordIterator.following(fNext); 409 } else 410 fSuccessor= BreakIterator.DONE; 411 } 412 413 416 public final boolean startsSentence() { 417 return fStartsSentence; 418 } 419 } 420 | Popular Tags |