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

changeset 1281
067f51db3402
parent 1125
56830d5cb5bb
child 1282
3468519d9b45
     1.1 --- a/src/share/classes/com/sun/tools/javac/parser/JavadocTokenizer.java	Wed Jun 20 13:23:26 2012 -0700
     1.2 +++ b/src/share/classes/com/sun/tools/javac/parser/JavadocTokenizer.java	Thu Jun 21 13:22:21 2012 -0700
     1.3 @@ -1,5 +1,5 @@
     1.4  /*
     1.5 - * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
     1.6 + * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
     1.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.8   *
     1.9   * This code is free software; you can redistribute it and/or modify it
    1.10 @@ -62,19 +62,54 @@
    1.11      @Override
    1.12      protected Comment processComment(int pos, int endPos, CommentStyle style) {
    1.13          char[] buf = reader.getRawCharacters(pos, endPos);
    1.14 -        return new JavadocComment(new ColReader(fac, buf, buf.length), style);
    1.15 +        return new JavadocComment(new DocReader(fac, buf, buf.length, pos), style);
    1.16      }
    1.17  
    1.18      /**
    1.19       * This is a specialized version of UnicodeReader that keeps track of the
    1.20 -     * column position within a given character stream (used for Javadoc processing).
    1.21 +     * column position within a given character stream (used for Javadoc processing),
    1.22 +     * and which builds a table for mapping positions in the comment string to
    1.23 +     * positions in the source file.
    1.24       */
    1.25 -    static class ColReader extends UnicodeReader {
    1.26 +    static class DocReader extends UnicodeReader {
    1.27  
    1.28           int col;
    1.29 +         int startPos;
    1.30  
    1.31 -         ColReader(ScannerFactory fac, char[] input, int inputLength) {
    1.32 +         /**
    1.33 +          * A buffer for building a table for mapping positions in {@link #sbuf}
    1.34 +          * to positions in the source buffer.
    1.35 +          *
    1.36 +          * The array is organized as a series of pairs of integers: the first
    1.37 +          * number in each pair specifies a position in the comment text,
    1.38 +          * the second number in each pair specifies the corresponding position
    1.39 +          * in the source buffer. The pairs are sorted in ascending order.
    1.40 +          *
    1.41 +          * Since the mapping function is generally continuous, with successive
    1.42 +          * positions in the string corresponding to successive positions in the
    1.43 +          * source buffer, the table only needs to record discontinuities in
    1.44 +          * the mapping. The values of intermediate positions can be inferred.
    1.45 +          *
    1.46 +          * Discontinuities may occur in a number of places: when a newline
    1.47 +          * is followed by whitespace and asterisks (which are ignored),
    1.48 +          * when a tab is expanded into spaces, and when unicode escapes
    1.49 +          * are used in the source buffer.
    1.50 +          *
    1.51 +          * Thus, to find the source position of any position, p, in the comment
    1.52 +          * string, find the index, i, of the pair whose string offset
    1.53 +          * ({@code pbuf[i] }) is closest to but not greater than p. Then,
    1.54 +          * {@code sourcePos(p) = pbuf[i+1] + (p - pbuf[i]) }.
    1.55 +          */
    1.56 +         int[] pbuf = new int[128];
    1.57 +
    1.58 +         /**
    1.59 +          * The index of the next empty slot in the pbuf buffer.
    1.60 +          */
    1.61 +         int pp = 0;
    1.62 +
    1.63 +         DocReader(ScannerFactory fac, char[] input, int inputLength, int startPos) {
    1.64               super(fac, input, inputLength);
    1.65 +             this.startPos = startPos;
    1.66           }
    1.67  
    1.68           @Override
    1.69 @@ -147,19 +182,43 @@
    1.70                   break;
    1.71               }
    1.72           }
    1.73 +
    1.74 +         @Override
    1.75 +         public void putChar(char ch, boolean scan) {
    1.76 +             // At this point, bp is the position of the current character in buf,
    1.77 +             // and sp is the position in sbuf where this character will be put.
    1.78 +             // Record a new entry in pbuf if pbuf is empty or if sp and its
    1.79 +             // corresponding source position are not equidistant from the
    1.80 +             // corresponding values in the latest entry in the pbuf array.
    1.81 +             // (i.e. there is a discontinuity in the map function.)
    1.82 +             if ((pp == 0)
    1.83 +                     || (sp - pbuf[pp - 2] != (startPos + bp) - pbuf[pp - 1])) {
    1.84 +                 if (pp + 1 >= pbuf.length) {
    1.85 +                     int[] new_pbuf = new int[pbuf.length * 2];
    1.86 +                     System.arraycopy(pbuf, 0, new_pbuf, 0, pbuf.length);
    1.87 +                     pbuf = new_pbuf;
    1.88 +                 }
    1.89 +                 pbuf[pp] = sp;
    1.90 +                 pbuf[pp + 1] = startPos + bp;
    1.91 +                 pp += 2;
    1.92 +             }
    1.93 +             super.putChar(ch, scan);
    1.94 +         }
    1.95       }
    1.96  
    1.97 -     protected class JavadocComment extends JavaTokenizer.BasicComment<ColReader> {
    1.98 +     protected class JavadocComment extends JavaTokenizer.BasicComment<DocReader> {
    1.99  
   1.100          /**
   1.101          * Translated and stripped contents of doc comment
   1.102          */
   1.103          private String docComment = null;
   1.104 +        private int[] docPosns = null;
   1.105  
   1.106 -        JavadocComment(ColReader comment_reader, CommentStyle cs) {
   1.107 -            super(comment_reader, cs);
   1.108 +        JavadocComment(DocReader reader, CommentStyle cs) {
   1.109 +            super(reader, cs);
   1.110          }
   1.111  
   1.112 +        @Override
   1.113          public String getText() {
   1.114              if (!scanned && cs == CommentStyle.JAVADOC) {
   1.115                  scanDocComment();
   1.116 @@ -168,6 +227,33 @@
   1.117          }
   1.118  
   1.119          @Override
   1.120 +        public int getSourcePos(int pos) {
   1.121 +            // Binary search to find the entry for which the string index is
   1.122 +            // less than pos. Since docPosns is a list of pairs of integers
   1.123 +            // we must make sure the index is always even.
   1.124 +            // If we find an exact match for pos, the other item in the pair
   1.125 +            // gives the source pos; otherwise, compute the source position
   1.126 +            // relative to the best match found in the array.
   1.127 +            if (pos < 0 || pos >= docComment.length())
   1.128 +                throw new StringIndexOutOfBoundsException();
   1.129 +            if (docPosns == null)
   1.130 +                return -1;
   1.131 +            int start = 0;
   1.132 +            int end = docPosns.length;
   1.133 +            while (start < end - 2) {
   1.134 +                // find an even index midway between start and end
   1.135 +                int index = ((start  + end) / 4) * 2;
   1.136 +                if (docPosns[index] < pos)
   1.137 +                    start = index;
   1.138 +                else if (docPosns[index] == pos)
   1.139 +                    return docPosns[index + 1];
   1.140 +                else
   1.141 +                    end = index;
   1.142 +            }
   1.143 +            return docPosns[start + 1] + (pos - docPosns[start]);
   1.144 +        }
   1.145 +
   1.146 +        @Override
   1.147          @SuppressWarnings("fallthrough")
   1.148          protected void scanDocComment() {
   1.149               try {
   1.150 @@ -209,7 +295,8 @@
   1.151                   // whitespace, then it consumes any stars, then it
   1.152                   // puts the rest of the line into our buffer.
   1.153                   while (comment_reader.bp < comment_reader.buflen) {
   1.154 -
   1.155 +                     int begin_bp = comment_reader.bp;
   1.156 +                     char begin_ch = comment_reader.ch;
   1.157                       // The wsLoop consumes whitespace from the beginning
   1.158                       // of each line.
   1.159                   wsLoop:
   1.160 @@ -263,10 +350,10 @@
   1.161                               break outerLoop;
   1.162                           }
   1.163                       } else if (! firstLine) {
   1.164 -                         //The current line does not begin with a '*' so we will indent it.
   1.165 -                         for (int i = 1; i < comment_reader.col; i++) {
   1.166 -                             comment_reader.putChar(' ', false);
   1.167 -                         }
   1.168 +                         // The current line does not begin with a '*' so we will
   1.169 +                         // treat it as comment
   1.170 +                         comment_reader.bp = begin_bp;
   1.171 +                         comment_reader.ch = begin_ch;
   1.172                       }
   1.173                       // The textLoop processes the rest of the characters
   1.174                       // on the line, adding them to our buffer.
   1.175 @@ -334,6 +421,8 @@
   1.176  
   1.177                       // Store the text of the doc comment
   1.178                      docComment = comment_reader.chars();
   1.179 +                    docPosns = new int[comment_reader.pp];
   1.180 +                    System.arraycopy(comment_reader.pbuf, 0, docPosns, 0, docPosns.length);
   1.181                  } else {
   1.182                      docComment = "";
   1.183                  }

mercurial