1 11 package org.eclipse.jdt.internal.core.dom.rewrite; 12 13 import org.eclipse.core.runtime.CoreException; 14 import org.eclipse.core.runtime.IStatus; 15 import org.eclipse.core.runtime.Status; 16 17 import org.eclipse.jface.text.BadLocationException; 18 import org.eclipse.jface.text.IDocument; 19 import org.eclipse.jface.text.IRegion; 20 21 import org.eclipse.jdt.core.JavaCore; 22 import org.eclipse.jdt.core.ToolFactory; 23 import org.eclipse.jdt.core.compiler.IScanner; 24 import org.eclipse.jdt.core.compiler.ITerminalSymbols; 25 import org.eclipse.jdt.core.compiler.InvalidInputException; 26 27 30 public class TokenScanner { 31 32 public static final int END_OF_FILE= 20001; 33 public static final int LEXICAL_ERROR= 20002; 34 public static final int DOCUMENT_ERROR= 20003; 35 36 private final IScanner scanner; 37 private final IDocument document; 38 private final int endPosition; 39 40 45 public TokenScanner(IScanner scanner) { 46 this(scanner, null); 47 } 48 49 54 public TokenScanner(IScanner scanner, IDocument document) { 55 this.scanner= scanner; 56 this.endPosition= this.scanner.getSource().length - 1; 57 this.document= document; 58 } 59 60 64 public TokenScanner(IDocument document) { 65 this.scanner= ToolFactory.createScanner(true, false, false, false); 66 this.scanner.setSource(document.get().toCharArray()); 67 this.document= document; 68 this.endPosition= this.scanner.getSource().length - 1; 69 } 70 71 75 public IScanner getScanner() { 76 return this.scanner; 77 } 78 79 83 public void setOffset(int offset) { 84 this.scanner.resetTo(offset, this.endPosition); 85 } 86 87 90 public int getCurrentEndOffset() { 91 return this.scanner.getCurrentTokenEndPosition() + 1; 92 } 93 94 97 public int getCurrentStartOffset() { 98 return this.scanner.getCurrentTokenStartPosition(); 99 } 100 101 104 public int getCurrentLength() { 105 return getCurrentEndOffset() - getCurrentStartOffset(); 106 } 107 108 115 public int readNext(boolean ignoreComments) throws CoreException { 116 int curr= 0; 117 do { 118 try { 119 curr= this.scanner.getNextToken(); 120 if (curr == ITerminalSymbols.TokenNameEOF) { 121 throw new CoreException(createError(END_OF_FILE, "End Of File", null)); } 123 } catch (InvalidInputException e) { 124 throw new CoreException(createError(LEXICAL_ERROR, e.getMessage(), e)); } 126 } while (ignoreComments && isComment(curr)); 127 return curr; 128 } 129 130 137 private int readNextWithEOF(boolean ignoreComments) throws CoreException { 138 int curr= 0; 139 do { 140 try { 141 curr= this.scanner.getNextToken(); 142 } catch (InvalidInputException e) { 143 throw new CoreException(createError(LEXICAL_ERROR, e.getMessage(), e)); } 145 } while (ignoreComments && isComment(curr)); 146 return curr; 147 } 148 149 157 public int readNext(int offset, boolean ignoreComments) throws CoreException { 158 setOffset(offset); 159 return readNext(ignoreComments); 160 } 161 162 170 public int getNextStartOffset(int offset, boolean ignoreComments) throws CoreException { 171 readNext(offset, ignoreComments); 172 return getCurrentStartOffset(); 173 } 174 175 183 public int getNextEndOffset(int offset, boolean ignoreComments) throws CoreException { 184 readNext(offset, ignoreComments); 185 return getCurrentEndOffset(); 186 } 187 188 194 public void readToToken(int tok) throws CoreException { 195 int curr= 0; 196 do { 197 curr= readNext(false); 198 } while (curr != tok); 199 } 200 201 208 public void readToToken(int tok, int offset) throws CoreException { 209 setOffset(offset); 210 readToToken(tok); 211 } 212 213 221 public int getTokenStartOffset(int token, int startOffset) throws CoreException { 222 readToToken(token, startOffset); 223 return getCurrentStartOffset(); 224 } 225 226 234 public int getTokenEndOffset(int token, int startOffset) throws CoreException { 235 readToToken(token, startOffset); 236 return getCurrentEndOffset(); 237 } 238 239 247 public int getPreviousTokenEndOffset(int token, int startOffset) throws CoreException { 248 setOffset(startOffset); 249 int res= startOffset; 250 int curr= readNext(false); 251 while (curr != token) { 252 res= getCurrentEndOffset(); 253 curr= readNext(false); 254 } 255 return res; 256 } 257 258 266 public int getTokenCommentStart(int lastPos, int nodeStart) throws CoreException { 267 setOffset(lastPos); 268 269 int prevEndPos= lastPos; 270 int prevEndLine= prevEndPos > 0 ? getLineOfOffset(prevEndPos - 1) : 0; 271 int nodeLine= getLineOfOffset(nodeStart); 272 273 int res= -1; 274 275 int curr= readNextWithEOF(false); 276 int currStartPos= getCurrentStartOffset(); 277 int currStartLine= getLineOfOffset(currStartPos); 278 while (curr != ITerminalSymbols.TokenNameEOF && nodeStart > currStartPos) { 279 if (TokenScanner.isComment(curr)) { 280 int linesDifference= currStartLine - prevEndLine; 281 if ((linesDifference > 1) || (res == -1 && (linesDifference != 0 || nodeLine == currStartLine))) { 282 res= currStartPos; } 284 } else { 285 res= -1; 286 } 287 288 if (curr == ITerminalSymbols.TokenNameCOMMENT_LINE) { 289 prevEndLine= currStartLine; 290 } else { 291 prevEndLine= getLineOfOffset(getCurrentEndOffset() - 1); 292 } 293 curr= readNextWithEOF(false); 294 currStartPos= getCurrentStartOffset(); 295 currStartLine= getLineOfOffset(currStartPos); 296 } 297 if (res == -1 || curr == ITerminalSymbols.TokenNameEOF) { 298 return nodeStart; 299 } 300 if (currStartLine - prevEndLine > 1) { 301 return nodeStart; 302 } 303 return res; 304 } 305 306 315 public int getTokenCommentEnd(int nodeEnd, int nextTokenStart) throws CoreException { 316 330 int prevEndLine= getLineOfOffset(nodeEnd - 1); 331 int prevEndPos= nodeEnd; 332 int res= nodeEnd; 333 boolean sameLineComment= true; 334 335 setOffset(nodeEnd); 336 337 338 int curr= readNextWithEOF(false); 339 while (curr == ITerminalSymbols.TokenNameCOMMENT_LINE || curr == ITerminalSymbols.TokenNameCOMMENT_BLOCK) { 340 int currStartLine= getLineOfOffset(getCurrentStartOffset()); 341 int linesDifference= currStartLine - prevEndLine; 342 343 if (linesDifference > 1) { 344 return prevEndPos; } 346 347 if (curr == ITerminalSymbols.TokenNameCOMMENT_LINE) { 348 prevEndPos= getLineEnd(currStartLine); 349 prevEndLine= currStartLine; 350 } else { 351 prevEndPos= getCurrentEndOffset(); 352 prevEndLine= getLineOfOffset(prevEndPos - 1); 353 } 354 if (sameLineComment) { 355 if (linesDifference == 0) { 356 res= prevEndPos; 357 } else { 358 sameLineComment= false; 359 } 360 } 361 curr= readNextWithEOF(false); 362 } 363 if (curr == ITerminalSymbols.TokenNameEOF) { 364 return prevEndPos; 365 } 366 int currStartLine= getLineOfOffset(getCurrentStartOffset()); 367 int linesDifference= currStartLine - prevEndLine; 368 if (linesDifference > 1) { 369 return prevEndPos; } 371 return res; 372 } 373 374 private int getLineOfOffset(int offset) throws CoreException { 375 if (this.document != null) { 376 try { 377 return this.document.getLineOfOffset(offset); 378 } catch (BadLocationException e) { 379 String message= "Illegal offset: " + offset; throw new CoreException(createError(DOCUMENT_ERROR, message, e)); } 382 } 383 return getScanner().getLineNumber(offset); 384 } 385 386 private int getLineEnd(int line) throws CoreException { 387 if (this.document != null) { 388 try { 389 IRegion region= this.document.getLineInformation(line); 390 return region.getOffset() + region.getLength(); 391 } catch (BadLocationException e) { 392 String message= "Illegal line: " + line; throw new CoreException(createError(DOCUMENT_ERROR, message, e)); } 395 } 396 return getScanner().getLineEnd(line); 397 } 398 399 400 public static boolean isComment(int token) { 401 return token == ITerminalSymbols.TokenNameCOMMENT_BLOCK || token == ITerminalSymbols.TokenNameCOMMENT_JAVADOC 402 || token == ITerminalSymbols.TokenNameCOMMENT_LINE; 403 } 404 405 public static boolean isModifier(int token) { 406 switch (token) { 407 case ITerminalSymbols.TokenNamepublic: 408 case ITerminalSymbols.TokenNameprotected: 409 case ITerminalSymbols.TokenNameprivate: 410 case ITerminalSymbols.TokenNamestatic: 411 case ITerminalSymbols.TokenNamefinal: 412 case ITerminalSymbols.TokenNameabstract: 413 case ITerminalSymbols.TokenNamenative: 414 case ITerminalSymbols.TokenNamevolatile: 415 case ITerminalSymbols.TokenNamestrictfp: 416 case ITerminalSymbols.TokenNametransient: 417 case ITerminalSymbols.TokenNamesynchronized: 418 return true; 419 default: 420 return false; 421 } 422 } 423 424 public static IStatus createError(int code, String message, Throwable throwable) { 425 return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, code, message, throwable); 426 } 427 428 } 429 | Popular Tags |