1.1 --- a/src/share/classes/com/sun/tools/javac/parser/JavadocTokenizer.java Tue Nov 01 15:49:45 2011 -0700 1.2 +++ b/src/share/classes/com/sun/tools/javac/parser/JavadocTokenizer.java Fri Nov 04 12:36:40 2011 +0000 1.3 @@ -25,8 +25,8 @@ 1.4 1.5 package com.sun.tools.javac.parser; 1.6 1.7 -import com.sun.tools.javac.file.JavacFileManager; 1.8 -import com.sun.tools.javac.parser.Tokens.Token; 1.9 +import com.sun.tools.javac.parser.Tokens.Comment; 1.10 +import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle; 1.11 import com.sun.tools.javac.util.*; 1.12 1.13 import java.nio.*; 1.14 @@ -59,352 +59,295 @@ 1.15 super(fac, input, inputLength); 1.16 } 1.17 1.18 - /** The comment input buffer, index of next chacter to be read, 1.19 - * index of one past last character in buffer. 1.20 - */ 1.21 - private char[] buf; 1.22 - private int bp; 1.23 - private int buflen; 1.24 - 1.25 - /** The current character. 1.26 - */ 1.27 - private char ch; 1.28 - 1.29 - /** The column number position of the current character. 1.30 - */ 1.31 - private int col; 1.32 - 1.33 - /** The buffer index of the last converted Unicode character 1.34 - */ 1.35 - private int unicodeConversionBp = 0; 1.36 + @Override 1.37 + protected Comment processComment(int pos, int endPos, CommentStyle style) { 1.38 + char[] buf = reader.getRawCharacters(pos, endPos); 1.39 + return new JavadocComment(new ColReader(fac, buf, buf.length), style); 1.40 + } 1.41 1.42 /** 1.43 - * Buffer for doc comment. 1.44 + * This is a specialized version of UnicodeReader that keeps track of the 1.45 + * column position within a given character stream (used for Javadoc processing). 1.46 */ 1.47 - private char[] docCommentBuffer = new char[1024]; 1.48 + static class ColReader extends UnicodeReader { 1.49 1.50 - /** 1.51 - * Number of characters in doc comment buffer. 1.52 - */ 1.53 - private int docCommentCount; 1.54 + int col; 1.55 1.56 - /** 1.57 - * Translated and stripped contents of doc comment 1.58 - */ 1.59 - private String docComment = null; 1.60 + ColReader(ScannerFactory fac, char[] input, int inputLength) { 1.61 + super(fac, input, inputLength); 1.62 + } 1.63 1.64 + @Override 1.65 + protected void convertUnicode() { 1.66 + if (ch == '\\' && unicodeConversionBp != bp) { 1.67 + bp++; ch = buf[bp]; col++; 1.68 + if (ch == 'u') { 1.69 + do { 1.70 + bp++; ch = buf[bp]; col++; 1.71 + } while (ch == 'u'); 1.72 + int limit = bp + 3; 1.73 + if (limit < buflen) { 1.74 + int d = digit(bp, 16); 1.75 + int code = d; 1.76 + while (bp < limit && d >= 0) { 1.77 + bp++; ch = buf[bp]; col++; 1.78 + d = digit(bp, 16); 1.79 + code = (code << 4) + d; 1.80 + } 1.81 + if (d >= 0) { 1.82 + ch = (char)code; 1.83 + unicodeConversionBp = bp; 1.84 + return; 1.85 + } 1.86 + } 1.87 + // "illegal.Unicode.esc", reported by base scanner 1.88 + } else { 1.89 + bp--; 1.90 + ch = '\\'; 1.91 + col--; 1.92 + } 1.93 + } 1.94 + } 1.95 1.96 - /** Unconditionally expand the comment buffer. 1.97 - */ 1.98 - private void expandCommentBuffer() { 1.99 - char[] newBuffer = new char[docCommentBuffer.length * 2]; 1.100 - System.arraycopy(docCommentBuffer, 0, newBuffer, 1.101 - 0, docCommentBuffer.length); 1.102 - docCommentBuffer = newBuffer; 1.103 - } 1.104 + @Override 1.105 + protected void scanCommentChar() { 1.106 + scanChar(); 1.107 + if (ch == '\\') { 1.108 + if (peekChar() == '\\' && !isUnicode()) { 1.109 + putChar(ch, false); 1.110 + bp++; col++; 1.111 + } else { 1.112 + convertUnicode(); 1.113 + } 1.114 + } 1.115 + } 1.116 1.117 - /** Convert an ASCII digit from its base (8, 10, or 16) 1.118 - * to its value. 1.119 - */ 1.120 - private int digit(int base) { 1.121 - char c = ch; 1.122 - int result = Character.digit(c, base); 1.123 - if (result >= 0 && c > 0x7f) { 1.124 - ch = "0123456789abcdef".charAt(result); 1.125 + @Override 1.126 + protected void scanChar() { 1.127 + bp++; 1.128 + ch = buf[bp]; 1.129 + switch (ch) { 1.130 + case '\r': // return 1.131 + col = 0; 1.132 + break; 1.133 + case '\n': // newline 1.134 + if (bp == 0 || buf[bp-1] != '\r') { 1.135 + col = 0; 1.136 + } 1.137 + break; 1.138 + case '\t': // tab 1.139 + col = (col / TabInc * TabInc) + TabInc; 1.140 + break; 1.141 + case '\\': // possible Unicode 1.142 + col++; 1.143 + convertUnicode(); 1.144 + break; 1.145 + default: 1.146 + col++; 1.147 + break; 1.148 + } 1.149 + } 1.150 + } 1.151 + 1.152 + protected class JavadocComment extends JavaTokenizer.BasicComment<ColReader> { 1.153 + 1.154 + /** 1.155 + * Translated and stripped contents of doc comment 1.156 + */ 1.157 + private String docComment = null; 1.158 + 1.159 + JavadocComment(ColReader comment_reader, CommentStyle cs) { 1.160 + super(comment_reader, cs); 1.161 } 1.162 - return result; 1.163 - } 1.164 1.165 - /** Convert Unicode escape; bp points to initial '\' character 1.166 - * (Spec 3.3). 1.167 - */ 1.168 - private void convertUnicode() { 1.169 - if (ch == '\\' && unicodeConversionBp != bp) { 1.170 - bp++; ch = buf[bp]; col++; 1.171 - if (ch == 'u') { 1.172 - do { 1.173 - bp++; ch = buf[bp]; col++; 1.174 - } while (ch == 'u'); 1.175 - int limit = bp + 3; 1.176 - if (limit < buflen) { 1.177 - int d = digit(16); 1.178 - int code = d; 1.179 - while (bp < limit && d >= 0) { 1.180 - bp++; ch = buf[bp]; col++; 1.181 - d = digit(16); 1.182 - code = (code << 4) + d; 1.183 - } 1.184 - if (d >= 0) { 1.185 - ch = (char)code; 1.186 - unicodeConversionBp = bp; 1.187 - return; 1.188 - } 1.189 + public String getText() { 1.190 + if (!scanned && cs == CommentStyle.JAVADOC) { 1.191 + scanDocComment(); 1.192 + } 1.193 + return docComment; 1.194 + } 1.195 + 1.196 + @Override 1.197 + @SuppressWarnings("fallthrough") 1.198 + protected void scanDocComment() { 1.199 + try { 1.200 + boolean firstLine = true; 1.201 + 1.202 + // Skip over first slash 1.203 + comment_reader.scanCommentChar(); 1.204 + // Skip over first star 1.205 + comment_reader.scanCommentChar(); 1.206 + 1.207 + // consume any number of stars 1.208 + while (comment_reader.bp < comment_reader.buflen && comment_reader.ch == '*') { 1.209 + comment_reader.scanCommentChar(); 1.210 + } 1.211 + // is the comment in the form /**/, /***/, /****/, etc. ? 1.212 + if (comment_reader.bp < comment_reader.buflen && comment_reader.ch == '/') { 1.213 + docComment = ""; 1.214 + return; 1.215 + } 1.216 + 1.217 + // skip a newline on the first line of the comment. 1.218 + if (comment_reader.bp < comment_reader.buflen) { 1.219 + if (comment_reader.ch == LF) { 1.220 + comment_reader.scanCommentChar(); 1.221 + firstLine = false; 1.222 + } else if (comment_reader.ch == CR) { 1.223 + comment_reader.scanCommentChar(); 1.224 + if (comment_reader.ch == LF) { 1.225 + comment_reader.scanCommentChar(); 1.226 + firstLine = false; 1.227 + } 1.228 + } 1.229 + } 1.230 + 1.231 + outerLoop: 1.232 + 1.233 + // The outerLoop processes the doc comment, looping once 1.234 + // for each line. For each line, it first strips off 1.235 + // whitespace, then it consumes any stars, then it 1.236 + // puts the rest of the line into our buffer. 1.237 + while (comment_reader.bp < comment_reader.buflen) { 1.238 + 1.239 + // The wsLoop consumes whitespace from the beginning 1.240 + // of each line. 1.241 + wsLoop: 1.242 + 1.243 + while (comment_reader.bp < comment_reader.buflen) { 1.244 + switch(comment_reader.ch) { 1.245 + case ' ': 1.246 + comment_reader.scanCommentChar(); 1.247 + break; 1.248 + case '\t': 1.249 + comment_reader.col = ((comment_reader.col - 1) / TabInc * TabInc) + TabInc; 1.250 + comment_reader.scanCommentChar(); 1.251 + break; 1.252 + case FF: 1.253 + comment_reader.col = 0; 1.254 + comment_reader.scanCommentChar(); 1.255 + break; 1.256 + // Treat newline at beginning of line (blank line, no star) 1.257 + // as comment text. Old Javadoc compatibility requires this. 1.258 + /*---------------------------------* 1.259 + case CR: // (Spec 3.4) 1.260 + doc_reader.scanCommentChar(); 1.261 + if (ch == LF) { 1.262 + col = 0; 1.263 + doc_reader.scanCommentChar(); 1.264 + } 1.265 + break; 1.266 + case LF: // (Spec 3.4) 1.267 + doc_reader.scanCommentChar(); 1.268 + break; 1.269 + *---------------------------------*/ 1.270 + default: 1.271 + // we've seen something that isn't whitespace; 1.272 + // jump out. 1.273 + break wsLoop; 1.274 + } 1.275 + } 1.276 + 1.277 + // Are there stars here? If so, consume them all 1.278 + // and check for the end of comment. 1.279 + if (comment_reader.ch == '*') { 1.280 + // skip all of the stars 1.281 + do { 1.282 + comment_reader.scanCommentChar(); 1.283 + } while (comment_reader.ch == '*'); 1.284 + 1.285 + // check for the closing slash. 1.286 + if (comment_reader.ch == '/') { 1.287 + // We're done with the doc comment 1.288 + // scanChar() and breakout. 1.289 + break outerLoop; 1.290 + } 1.291 + } else if (! firstLine) { 1.292 + //The current line does not begin with a '*' so we will indent it. 1.293 + for (int i = 1; i < comment_reader.col; i++) { 1.294 + comment_reader.putChar(' ', false); 1.295 + } 1.296 + } 1.297 + // The textLoop processes the rest of the characters 1.298 + // on the line, adding them to our buffer. 1.299 + textLoop: 1.300 + while (comment_reader.bp < comment_reader.buflen) { 1.301 + switch (comment_reader.ch) { 1.302 + case '*': 1.303 + // Is this just a star? Or is this the 1.304 + // end of a comment? 1.305 + comment_reader.scanCommentChar(); 1.306 + if (comment_reader.ch == '/') { 1.307 + // This is the end of the comment, 1.308 + // set ch and return our buffer. 1.309 + break outerLoop; 1.310 + } 1.311 + // This is just an ordinary star. Add it to 1.312 + // the buffer. 1.313 + comment_reader.putChar('*', false); 1.314 + break; 1.315 + case ' ': 1.316 + case '\t': 1.317 + comment_reader.putChar(comment_reader.ch, false); 1.318 + comment_reader.scanCommentChar(); 1.319 + break; 1.320 + case FF: 1.321 + comment_reader.scanCommentChar(); 1.322 + break textLoop; // treat as end of line 1.323 + case CR: // (Spec 3.4) 1.324 + comment_reader.scanCommentChar(); 1.325 + if (comment_reader.ch != LF) { 1.326 + // Canonicalize CR-only line terminator to LF 1.327 + comment_reader.putChar((char)LF, false); 1.328 + break textLoop; 1.329 + } 1.330 + /* fall through to LF case */ 1.331 + case LF: // (Spec 3.4) 1.332 + // We've seen a newline. Add it to our 1.333 + // buffer and break out of this loop, 1.334 + // starting fresh on a new line. 1.335 + comment_reader.putChar(comment_reader.ch, false); 1.336 + comment_reader.scanCommentChar(); 1.337 + break textLoop; 1.338 + default: 1.339 + // Add the character to our buffer. 1.340 + comment_reader.putChar(comment_reader.ch, false); 1.341 + comment_reader.scanCommentChar(); 1.342 + } 1.343 + } // end textLoop 1.344 + firstLine = false; 1.345 + } // end outerLoop 1.346 + 1.347 + if (comment_reader.sp > 0) { 1.348 + int i = comment_reader.sp - 1; 1.349 + trailLoop: 1.350 + while (i > -1) { 1.351 + switch (comment_reader.sbuf[i]) { 1.352 + case '*': 1.353 + i--; 1.354 + break; 1.355 + default: 1.356 + break trailLoop; 1.357 + } 1.358 + } 1.359 + comment_reader.sp = i + 1; 1.360 + 1.361 + // Store the text of the doc comment 1.362 + docComment = comment_reader.chars(); 1.363 + } else { 1.364 + docComment = ""; 1.365 } 1.366 - // "illegal.Unicode.esc", reported by base scanner 1.367 - } else { 1.368 - bp--; 1.369 - ch = '\\'; 1.370 - col--; 1.371 + } finally { 1.372 + scanned = true; 1.373 + if (docComment != null && 1.374 + docComment.matches("(?sm).*^\\s*@deprecated( |$).*")) { 1.375 + deprecatedFlag = true; 1.376 + } 1.377 } 1.378 } 1.379 } 1.380 1.381 - 1.382 - /** Read next character. 1.383 - */ 1.384 - private void scanChar() { 1.385 - bp++; 1.386 - ch = buf[bp]; 1.387 - switch (ch) { 1.388 - case '\r': // return 1.389 - col = 0; 1.390 - break; 1.391 - case '\n': // newline 1.392 - if (bp == 0 || buf[bp-1] != '\r') { 1.393 - col = 0; 1.394 - } 1.395 - break; 1.396 - case '\t': // tab 1.397 - col = (col / TabInc * TabInc) + TabInc; 1.398 - break; 1.399 - case '\\': // possible Unicode 1.400 - col++; 1.401 - convertUnicode(); 1.402 - break; 1.403 - default: 1.404 - col++; 1.405 - break; 1.406 - } 1.407 - } 1.408 - 1.409 @Override 1.410 - public Token readToken() { 1.411 - docComment = null; 1.412 - Token tk = super.readToken(); 1.413 - tk.docComment = docComment; 1.414 - return tk; 1.415 - } 1.416 - 1.417 - /** 1.418 - * Read next character in doc comment, skipping over double '\' characters. 1.419 - * If a double '\' is skipped, put in the buffer and update buffer count. 1.420 - */ 1.421 - private void scanDocCommentChar() { 1.422 - scanChar(); 1.423 - if (ch == '\\') { 1.424 - if (buf[bp+1] == '\\' && unicodeConversionBp != bp) { 1.425 - if (docCommentCount == docCommentBuffer.length) 1.426 - expandCommentBuffer(); 1.427 - docCommentBuffer[docCommentCount++] = ch; 1.428 - bp++; col++; 1.429 - } else { 1.430 - convertUnicode(); 1.431 - } 1.432 - } 1.433 - } 1.434 - 1.435 - /** 1.436 - * Process a doc comment and make the string content available. 1.437 - * Strips leading whitespace and stars. 1.438 - */ 1.439 - @SuppressWarnings("fallthrough") 1.440 - protected void processComment(int pos, int endPos, CommentStyle style) { 1.441 - if (style != CommentStyle.JAVADOC) { 1.442 - return; 1.443 - } 1.444 - 1.445 - buf = reader.getRawCharacters(pos, endPos); 1.446 - buflen = buf.length; 1.447 - bp = 0; 1.448 - col = 0; 1.449 - 1.450 - docCommentCount = 0; 1.451 - 1.452 - boolean firstLine = true; 1.453 - 1.454 - // Skip over first slash 1.455 - scanDocCommentChar(); 1.456 - // Skip over first star 1.457 - scanDocCommentChar(); 1.458 - 1.459 - // consume any number of stars 1.460 - while (bp < buflen && ch == '*') { 1.461 - scanDocCommentChar(); 1.462 - } 1.463 - // is the comment in the form /**/, /***/, /****/, etc. ? 1.464 - if (bp < buflen && ch == '/') { 1.465 - docComment = ""; 1.466 - return; 1.467 - } 1.468 - 1.469 - // skip a newline on the first line of the comment. 1.470 - if (bp < buflen) { 1.471 - if (ch == LF) { 1.472 - scanDocCommentChar(); 1.473 - firstLine = false; 1.474 - } else if (ch == CR) { 1.475 - scanDocCommentChar(); 1.476 - if (ch == LF) { 1.477 - scanDocCommentChar(); 1.478 - firstLine = false; 1.479 - } 1.480 - } 1.481 - } 1.482 - 1.483 - outerLoop: 1.484 - 1.485 - // The outerLoop processes the doc comment, looping once 1.486 - // for each line. For each line, it first strips off 1.487 - // whitespace, then it consumes any stars, then it 1.488 - // puts the rest of the line into our buffer. 1.489 - while (bp < buflen) { 1.490 - 1.491 - // The wsLoop consumes whitespace from the beginning 1.492 - // of each line. 1.493 - wsLoop: 1.494 - 1.495 - while (bp < buflen) { 1.496 - switch(ch) { 1.497 - case ' ': 1.498 - scanDocCommentChar(); 1.499 - break; 1.500 - case '\t': 1.501 - col = ((col - 1) / TabInc * TabInc) + TabInc; 1.502 - scanDocCommentChar(); 1.503 - break; 1.504 - case FF: 1.505 - col = 0; 1.506 - scanDocCommentChar(); 1.507 - break; 1.508 -// Treat newline at beginning of line (blank line, no star) 1.509 -// as comment text. Old Javadoc compatibility requires this. 1.510 -/*---------------------------------* 1.511 - case CR: // (Spec 3.4) 1.512 - scanDocCommentChar(); 1.513 - if (ch == LF) { 1.514 - col = 0; 1.515 - scanDocCommentChar(); 1.516 - } 1.517 - break; 1.518 - case LF: // (Spec 3.4) 1.519 - scanDocCommentChar(); 1.520 - break; 1.521 -*---------------------------------*/ 1.522 - default: 1.523 - // we've seen something that isn't whitespace; 1.524 - // jump out. 1.525 - break wsLoop; 1.526 - } 1.527 - } 1.528 - 1.529 - // Are there stars here? If so, consume them all 1.530 - // and check for the end of comment. 1.531 - if (ch == '*') { 1.532 - // skip all of the stars 1.533 - do { 1.534 - scanDocCommentChar(); 1.535 - } while (ch == '*'); 1.536 - 1.537 - // check for the closing slash. 1.538 - if (ch == '/') { 1.539 - // We're done with the doc comment 1.540 - // scanChar() and breakout. 1.541 - break outerLoop; 1.542 - } 1.543 - } else if (! firstLine) { 1.544 - //The current line does not begin with a '*' so we will indent it. 1.545 - for (int i = 1; i < col; i++) { 1.546 - if (docCommentCount == docCommentBuffer.length) 1.547 - expandCommentBuffer(); 1.548 - docCommentBuffer[docCommentCount++] = ' '; 1.549 - } 1.550 - } 1.551 - 1.552 - // The textLoop processes the rest of the characters 1.553 - // on the line, adding them to our buffer. 1.554 - textLoop: 1.555 - while (bp < buflen) { 1.556 - switch (ch) { 1.557 - case '*': 1.558 - // Is this just a star? Or is this the 1.559 - // end of a comment? 1.560 - scanDocCommentChar(); 1.561 - if (ch == '/') { 1.562 - // This is the end of the comment, 1.563 - // set ch and return our buffer. 1.564 - break outerLoop; 1.565 - } 1.566 - // This is just an ordinary star. Add it to 1.567 - // the buffer. 1.568 - if (docCommentCount == docCommentBuffer.length) 1.569 - expandCommentBuffer(); 1.570 - docCommentBuffer[docCommentCount++] = '*'; 1.571 - break; 1.572 - case ' ': 1.573 - case '\t': 1.574 - if (docCommentCount == docCommentBuffer.length) 1.575 - expandCommentBuffer(); 1.576 - docCommentBuffer[docCommentCount++] = ch; 1.577 - scanDocCommentChar(); 1.578 - break; 1.579 - case FF: 1.580 - scanDocCommentChar(); 1.581 - break textLoop; // treat as end of line 1.582 - case CR: // (Spec 3.4) 1.583 - scanDocCommentChar(); 1.584 - if (ch != LF) { 1.585 - // Canonicalize CR-only line terminator to LF 1.586 - if (docCommentCount == docCommentBuffer.length) 1.587 - expandCommentBuffer(); 1.588 - docCommentBuffer[docCommentCount++] = (char)LF; 1.589 - break textLoop; 1.590 - } 1.591 - /* fall through to LF case */ 1.592 - case LF: // (Spec 3.4) 1.593 - // We've seen a newline. Add it to our 1.594 - // buffer and break out of this loop, 1.595 - // starting fresh on a new line. 1.596 - if (docCommentCount == docCommentBuffer.length) 1.597 - expandCommentBuffer(); 1.598 - docCommentBuffer[docCommentCount++] = ch; 1.599 - scanDocCommentChar(); 1.600 - break textLoop; 1.601 - default: 1.602 - // Add the character to our buffer. 1.603 - if (docCommentCount == docCommentBuffer.length) 1.604 - expandCommentBuffer(); 1.605 - docCommentBuffer[docCommentCount++] = ch; 1.606 - scanDocCommentChar(); 1.607 - } 1.608 - } // end textLoop 1.609 - firstLine = false; 1.610 - } // end outerLoop 1.611 - 1.612 - if (docCommentCount > 0) { 1.613 - int i = docCommentCount - 1; 1.614 - trailLoop: 1.615 - while (i > -1) { 1.616 - switch (docCommentBuffer[i]) { 1.617 - case '*': 1.618 - i--; 1.619 - break; 1.620 - default: 1.621 - break trailLoop; 1.622 - } 1.623 - } 1.624 - docCommentCount = i + 1; 1.625 - 1.626 - // Store the text of the doc comment 1.627 - docComment = new String(docCommentBuffer, 0 , docCommentCount); 1.628 - } else { 1.629 - docComment = ""; 1.630 - } 1.631 - } 1.632 - 1.633 - /** Build a map for translating between line numbers and 1.634 - * positions in the input. 1.635 - * 1.636 - * @return a LineMap */ 1.637 public Position.LineMap getLineMap() { 1.638 char[] buf = reader.getRawCharacters(); 1.639 return Position.makeLineMap(buf, buf.length, true);