src/share/classes/com/sun/tools/javac/parser/JavadocTokenizer.java

Wed, 20 Jun 2012 13:23:26 -0700

author
jjg
date
Wed, 20 Jun 2012 13:23:26 -0700
changeset 1280
5c0b3faeb0b0
parent 1125
56830d5cb5bb
child 1281
067f51db3402
permissions
-rw-r--r--

7174143: encapsulate doc comment table
Reviewed-by: ksrini, mcimadamore

mcimadamore@1113 1 /*
mcimadamore@1113 2 * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
mcimadamore@1113 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
mcimadamore@1113 4 *
mcimadamore@1113 5 * This code is free software; you can redistribute it and/or modify it
mcimadamore@1113 6 * under the terms of the GNU General Public License version 2 only, as
mcimadamore@1113 7 * published by the Free Software Foundation. Oracle designates this
mcimadamore@1113 8 * particular file as subject to the "Classpath" exception as provided
mcimadamore@1113 9 * by Oracle in the LICENSE file that accompanied this code.
mcimadamore@1113 10 *
mcimadamore@1113 11 * This code is distributed in the hope that it will be useful, but WITHOUT
mcimadamore@1113 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
mcimadamore@1113 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
mcimadamore@1113 14 * version 2 for more details (a copy is included in the LICENSE file that
mcimadamore@1113 15 * accompanied this code).
mcimadamore@1113 16 *
mcimadamore@1113 17 * You should have received a copy of the GNU General Public License version
mcimadamore@1113 18 * 2 along with this work; if not, write to the Free Software Foundation,
mcimadamore@1113 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
mcimadamore@1113 20 *
mcimadamore@1113 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
mcimadamore@1113 22 * or visit www.oracle.com if you need additional information or have any
mcimadamore@1113 23 * questions.
mcimadamore@1113 24 */
mcimadamore@1113 25
mcimadamore@1113 26 package com.sun.tools.javac.parser;
mcimadamore@1113 27
mcimadamore@1125 28 import com.sun.tools.javac.parser.Tokens.Comment;
mcimadamore@1125 29 import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
mcimadamore@1113 30 import com.sun.tools.javac.util.*;
mcimadamore@1113 31
mcimadamore@1113 32 import java.nio.*;
mcimadamore@1113 33
mcimadamore@1113 34 import static com.sun.tools.javac.util.LayoutCharacters.*;
mcimadamore@1113 35
mcimadamore@1113 36 /** An extension to the base lexical analyzer that captures
mcimadamore@1113 37 * and processes the contents of doc comments. It does so by
mcimadamore@1113 38 * translating Unicode escape sequences and by stripping the
mcimadamore@1113 39 * leading whitespace and starts from each line of the comment.
mcimadamore@1113 40 *
mcimadamore@1113 41 * <p><b>This is NOT part of any supported API.
mcimadamore@1113 42 * If you write code that depends on this, you do so at your own risk.
mcimadamore@1113 43 * This code and its internal interfaces are subject to change or
mcimadamore@1113 44 * deletion without notice.</b>
mcimadamore@1113 45 */
mcimadamore@1113 46 public class JavadocTokenizer extends JavaTokenizer {
mcimadamore@1113 47
mcimadamore@1113 48 /** Create a scanner from the input buffer. buffer must implement
mcimadamore@1113 49 * array() and compact(), and remaining() must be less than limit().
mcimadamore@1113 50 */
mcimadamore@1113 51 protected JavadocTokenizer(ScannerFactory fac, CharBuffer buffer) {
mcimadamore@1113 52 super(fac, buffer);
mcimadamore@1113 53 }
mcimadamore@1113 54
mcimadamore@1113 55 /** Create a scanner from the input array. The array must have at
mcimadamore@1113 56 * least a single character of extra space.
mcimadamore@1113 57 */
mcimadamore@1113 58 protected JavadocTokenizer(ScannerFactory fac, char[] input, int inputLength) {
mcimadamore@1113 59 super(fac, input, inputLength);
mcimadamore@1113 60 }
mcimadamore@1113 61
mcimadamore@1125 62 @Override
mcimadamore@1125 63 protected Comment processComment(int pos, int endPos, CommentStyle style) {
mcimadamore@1125 64 char[] buf = reader.getRawCharacters(pos, endPos);
mcimadamore@1125 65 return new JavadocComment(new ColReader(fac, buf, buf.length), style);
mcimadamore@1125 66 }
mcimadamore@1113 67
mcimadamore@1113 68 /**
mcimadamore@1125 69 * This is a specialized version of UnicodeReader that keeps track of the
mcimadamore@1125 70 * column position within a given character stream (used for Javadoc processing).
mcimadamore@1113 71 */
mcimadamore@1125 72 static class ColReader extends UnicodeReader {
mcimadamore@1113 73
mcimadamore@1125 74 int col;
mcimadamore@1113 75
mcimadamore@1125 76 ColReader(ScannerFactory fac, char[] input, int inputLength) {
mcimadamore@1125 77 super(fac, input, inputLength);
mcimadamore@1125 78 }
mcimadamore@1113 79
mcimadamore@1125 80 @Override
mcimadamore@1125 81 protected void convertUnicode() {
mcimadamore@1125 82 if (ch == '\\' && unicodeConversionBp != bp) {
mcimadamore@1125 83 bp++; ch = buf[bp]; col++;
mcimadamore@1125 84 if (ch == 'u') {
mcimadamore@1125 85 do {
mcimadamore@1125 86 bp++; ch = buf[bp]; col++;
mcimadamore@1125 87 } while (ch == 'u');
mcimadamore@1125 88 int limit = bp + 3;
mcimadamore@1125 89 if (limit < buflen) {
mcimadamore@1125 90 int d = digit(bp, 16);
mcimadamore@1125 91 int code = d;
mcimadamore@1125 92 while (bp < limit && d >= 0) {
mcimadamore@1125 93 bp++; ch = buf[bp]; col++;
mcimadamore@1125 94 d = digit(bp, 16);
mcimadamore@1125 95 code = (code << 4) + d;
mcimadamore@1125 96 }
mcimadamore@1125 97 if (d >= 0) {
mcimadamore@1125 98 ch = (char)code;
mcimadamore@1125 99 unicodeConversionBp = bp;
mcimadamore@1125 100 return;
mcimadamore@1125 101 }
mcimadamore@1125 102 }
mcimadamore@1125 103 // "illegal.Unicode.esc", reported by base scanner
mcimadamore@1125 104 } else {
mcimadamore@1125 105 bp--;
mcimadamore@1125 106 ch = '\\';
mcimadamore@1125 107 col--;
mcimadamore@1125 108 }
mcimadamore@1125 109 }
mcimadamore@1125 110 }
mcimadamore@1113 111
mcimadamore@1125 112 @Override
mcimadamore@1125 113 protected void scanCommentChar() {
mcimadamore@1125 114 scanChar();
mcimadamore@1125 115 if (ch == '\\') {
mcimadamore@1125 116 if (peekChar() == '\\' && !isUnicode()) {
mcimadamore@1125 117 putChar(ch, false);
mcimadamore@1125 118 bp++; col++;
mcimadamore@1125 119 } else {
mcimadamore@1125 120 convertUnicode();
mcimadamore@1125 121 }
mcimadamore@1125 122 }
mcimadamore@1125 123 }
mcimadamore@1113 124
mcimadamore@1125 125 @Override
mcimadamore@1125 126 protected void scanChar() {
mcimadamore@1125 127 bp++;
mcimadamore@1125 128 ch = buf[bp];
mcimadamore@1125 129 switch (ch) {
mcimadamore@1125 130 case '\r': // return
mcimadamore@1125 131 col = 0;
mcimadamore@1125 132 break;
mcimadamore@1125 133 case '\n': // newline
mcimadamore@1125 134 if (bp == 0 || buf[bp-1] != '\r') {
mcimadamore@1125 135 col = 0;
mcimadamore@1125 136 }
mcimadamore@1125 137 break;
mcimadamore@1125 138 case '\t': // tab
mcimadamore@1125 139 col = (col / TabInc * TabInc) + TabInc;
mcimadamore@1125 140 break;
mcimadamore@1125 141 case '\\': // possible Unicode
mcimadamore@1125 142 col++;
mcimadamore@1125 143 convertUnicode();
mcimadamore@1125 144 break;
mcimadamore@1125 145 default:
mcimadamore@1125 146 col++;
mcimadamore@1125 147 break;
mcimadamore@1125 148 }
mcimadamore@1125 149 }
mcimadamore@1125 150 }
mcimadamore@1125 151
mcimadamore@1125 152 protected class JavadocComment extends JavaTokenizer.BasicComment<ColReader> {
mcimadamore@1125 153
mcimadamore@1125 154 /**
mcimadamore@1125 155 * Translated and stripped contents of doc comment
mcimadamore@1125 156 */
mcimadamore@1125 157 private String docComment = null;
mcimadamore@1125 158
mcimadamore@1125 159 JavadocComment(ColReader comment_reader, CommentStyle cs) {
mcimadamore@1125 160 super(comment_reader, cs);
mcimadamore@1113 161 }
mcimadamore@1113 162
mcimadamore@1125 163 public String getText() {
mcimadamore@1125 164 if (!scanned && cs == CommentStyle.JAVADOC) {
mcimadamore@1125 165 scanDocComment();
mcimadamore@1125 166 }
mcimadamore@1125 167 return docComment;
mcimadamore@1125 168 }
mcimadamore@1125 169
mcimadamore@1125 170 @Override
mcimadamore@1125 171 @SuppressWarnings("fallthrough")
mcimadamore@1125 172 protected void scanDocComment() {
mcimadamore@1125 173 try {
mcimadamore@1125 174 boolean firstLine = true;
mcimadamore@1125 175
mcimadamore@1125 176 // Skip over first slash
mcimadamore@1125 177 comment_reader.scanCommentChar();
mcimadamore@1125 178 // Skip over first star
mcimadamore@1125 179 comment_reader.scanCommentChar();
mcimadamore@1125 180
mcimadamore@1125 181 // consume any number of stars
mcimadamore@1125 182 while (comment_reader.bp < comment_reader.buflen && comment_reader.ch == '*') {
mcimadamore@1125 183 comment_reader.scanCommentChar();
mcimadamore@1125 184 }
mcimadamore@1125 185 // is the comment in the form /**/, /***/, /****/, etc. ?
mcimadamore@1125 186 if (comment_reader.bp < comment_reader.buflen && comment_reader.ch == '/') {
mcimadamore@1125 187 docComment = "";
mcimadamore@1125 188 return;
mcimadamore@1125 189 }
mcimadamore@1125 190
mcimadamore@1125 191 // skip a newline on the first line of the comment.
mcimadamore@1125 192 if (comment_reader.bp < comment_reader.buflen) {
mcimadamore@1125 193 if (comment_reader.ch == LF) {
mcimadamore@1125 194 comment_reader.scanCommentChar();
mcimadamore@1125 195 firstLine = false;
mcimadamore@1125 196 } else if (comment_reader.ch == CR) {
mcimadamore@1125 197 comment_reader.scanCommentChar();
mcimadamore@1125 198 if (comment_reader.ch == LF) {
mcimadamore@1125 199 comment_reader.scanCommentChar();
mcimadamore@1125 200 firstLine = false;
mcimadamore@1125 201 }
mcimadamore@1125 202 }
mcimadamore@1125 203 }
mcimadamore@1125 204
mcimadamore@1125 205 outerLoop:
mcimadamore@1125 206
mcimadamore@1125 207 // The outerLoop processes the doc comment, looping once
mcimadamore@1125 208 // for each line. For each line, it first strips off
mcimadamore@1125 209 // whitespace, then it consumes any stars, then it
mcimadamore@1125 210 // puts the rest of the line into our buffer.
mcimadamore@1125 211 while (comment_reader.bp < comment_reader.buflen) {
mcimadamore@1125 212
mcimadamore@1125 213 // The wsLoop consumes whitespace from the beginning
mcimadamore@1125 214 // of each line.
mcimadamore@1125 215 wsLoop:
mcimadamore@1125 216
mcimadamore@1125 217 while (comment_reader.bp < comment_reader.buflen) {
mcimadamore@1125 218 switch(comment_reader.ch) {
mcimadamore@1125 219 case ' ':
mcimadamore@1125 220 comment_reader.scanCommentChar();
mcimadamore@1125 221 break;
mcimadamore@1125 222 case '\t':
mcimadamore@1125 223 comment_reader.col = ((comment_reader.col - 1) / TabInc * TabInc) + TabInc;
mcimadamore@1125 224 comment_reader.scanCommentChar();
mcimadamore@1125 225 break;
mcimadamore@1125 226 case FF:
mcimadamore@1125 227 comment_reader.col = 0;
mcimadamore@1125 228 comment_reader.scanCommentChar();
mcimadamore@1125 229 break;
mcimadamore@1125 230 // Treat newline at beginning of line (blank line, no star)
mcimadamore@1125 231 // as comment text. Old Javadoc compatibility requires this.
mcimadamore@1125 232 /*---------------------------------*
mcimadamore@1125 233 case CR: // (Spec 3.4)
mcimadamore@1125 234 doc_reader.scanCommentChar();
mcimadamore@1125 235 if (ch == LF) {
mcimadamore@1125 236 col = 0;
mcimadamore@1125 237 doc_reader.scanCommentChar();
mcimadamore@1125 238 }
mcimadamore@1125 239 break;
mcimadamore@1125 240 case LF: // (Spec 3.4)
mcimadamore@1125 241 doc_reader.scanCommentChar();
mcimadamore@1125 242 break;
mcimadamore@1125 243 *---------------------------------*/
mcimadamore@1125 244 default:
mcimadamore@1125 245 // we've seen something that isn't whitespace;
mcimadamore@1125 246 // jump out.
mcimadamore@1125 247 break wsLoop;
mcimadamore@1125 248 }
mcimadamore@1125 249 }
mcimadamore@1125 250
mcimadamore@1125 251 // Are there stars here? If so, consume them all
mcimadamore@1125 252 // and check for the end of comment.
mcimadamore@1125 253 if (comment_reader.ch == '*') {
mcimadamore@1125 254 // skip all of the stars
mcimadamore@1125 255 do {
mcimadamore@1125 256 comment_reader.scanCommentChar();
mcimadamore@1125 257 } while (comment_reader.ch == '*');
mcimadamore@1125 258
mcimadamore@1125 259 // check for the closing slash.
mcimadamore@1125 260 if (comment_reader.ch == '/') {
mcimadamore@1125 261 // We're done with the doc comment
mcimadamore@1125 262 // scanChar() and breakout.
mcimadamore@1125 263 break outerLoop;
mcimadamore@1125 264 }
mcimadamore@1125 265 } else if (! firstLine) {
mcimadamore@1125 266 //The current line does not begin with a '*' so we will indent it.
mcimadamore@1125 267 for (int i = 1; i < comment_reader.col; i++) {
mcimadamore@1125 268 comment_reader.putChar(' ', false);
mcimadamore@1125 269 }
mcimadamore@1125 270 }
mcimadamore@1125 271 // The textLoop processes the rest of the characters
mcimadamore@1125 272 // on the line, adding them to our buffer.
mcimadamore@1125 273 textLoop:
mcimadamore@1125 274 while (comment_reader.bp < comment_reader.buflen) {
mcimadamore@1125 275 switch (comment_reader.ch) {
mcimadamore@1125 276 case '*':
mcimadamore@1125 277 // Is this just a star? Or is this the
mcimadamore@1125 278 // end of a comment?
mcimadamore@1125 279 comment_reader.scanCommentChar();
mcimadamore@1125 280 if (comment_reader.ch == '/') {
mcimadamore@1125 281 // This is the end of the comment,
mcimadamore@1125 282 // set ch and return our buffer.
mcimadamore@1125 283 break outerLoop;
mcimadamore@1125 284 }
mcimadamore@1125 285 // This is just an ordinary star. Add it to
mcimadamore@1125 286 // the buffer.
mcimadamore@1125 287 comment_reader.putChar('*', false);
mcimadamore@1125 288 break;
mcimadamore@1125 289 case ' ':
mcimadamore@1125 290 case '\t':
mcimadamore@1125 291 comment_reader.putChar(comment_reader.ch, false);
mcimadamore@1125 292 comment_reader.scanCommentChar();
mcimadamore@1125 293 break;
mcimadamore@1125 294 case FF:
mcimadamore@1125 295 comment_reader.scanCommentChar();
mcimadamore@1125 296 break textLoop; // treat as end of line
mcimadamore@1125 297 case CR: // (Spec 3.4)
mcimadamore@1125 298 comment_reader.scanCommentChar();
mcimadamore@1125 299 if (comment_reader.ch != LF) {
mcimadamore@1125 300 // Canonicalize CR-only line terminator to LF
mcimadamore@1125 301 comment_reader.putChar((char)LF, false);
mcimadamore@1125 302 break textLoop;
mcimadamore@1125 303 }
mcimadamore@1125 304 /* fall through to LF case */
mcimadamore@1125 305 case LF: // (Spec 3.4)
mcimadamore@1125 306 // We've seen a newline. Add it to our
mcimadamore@1125 307 // buffer and break out of this loop,
mcimadamore@1125 308 // starting fresh on a new line.
mcimadamore@1125 309 comment_reader.putChar(comment_reader.ch, false);
mcimadamore@1125 310 comment_reader.scanCommentChar();
mcimadamore@1125 311 break textLoop;
mcimadamore@1125 312 default:
mcimadamore@1125 313 // Add the character to our buffer.
mcimadamore@1125 314 comment_reader.putChar(comment_reader.ch, false);
mcimadamore@1125 315 comment_reader.scanCommentChar();
mcimadamore@1125 316 }
mcimadamore@1125 317 } // end textLoop
mcimadamore@1125 318 firstLine = false;
mcimadamore@1125 319 } // end outerLoop
mcimadamore@1125 320
mcimadamore@1125 321 if (comment_reader.sp > 0) {
mcimadamore@1125 322 int i = comment_reader.sp - 1;
mcimadamore@1125 323 trailLoop:
mcimadamore@1125 324 while (i > -1) {
mcimadamore@1125 325 switch (comment_reader.sbuf[i]) {
mcimadamore@1125 326 case '*':
mcimadamore@1125 327 i--;
mcimadamore@1125 328 break;
mcimadamore@1125 329 default:
mcimadamore@1125 330 break trailLoop;
mcimadamore@1125 331 }
mcimadamore@1125 332 }
mcimadamore@1125 333 comment_reader.sp = i + 1;
mcimadamore@1125 334
mcimadamore@1125 335 // Store the text of the doc comment
mcimadamore@1125 336 docComment = comment_reader.chars();
mcimadamore@1125 337 } else {
mcimadamore@1125 338 docComment = "";
mcimadamore@1113 339 }
mcimadamore@1125 340 } finally {
mcimadamore@1125 341 scanned = true;
mcimadamore@1125 342 if (docComment != null &&
mcimadamore@1125 343 docComment.matches("(?sm).*^\\s*@deprecated( |$).*")) {
mcimadamore@1125 344 deprecatedFlag = true;
mcimadamore@1125 345 }
mcimadamore@1113 346 }
mcimadamore@1113 347 }
mcimadamore@1113 348 }
mcimadamore@1113 349
mcimadamore@1113 350 @Override
mcimadamore@1113 351 public Position.LineMap getLineMap() {
mcimadamore@1113 352 char[] buf = reader.getRawCharacters();
mcimadamore@1113 353 return Position.makeLineMap(buf, buf.length, true);
mcimadamore@1113 354 }
mcimadamore@1113 355 }

mercurial