7178297: provide mapping from doc comment position to source file position

Thu, 21 Jun 2012 13:22:21 -0700

author
jjg
date
Thu, 21 Jun 2012 13:22:21 -0700
changeset 1281
067f51db3402
parent 1280
5c0b3faeb0b0
child 1282
3468519d9b45

7178297: provide mapping from doc comment position to source file position
Reviewed-by: mcimadamore, ksrini

src/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/parser/JavadocTokenizer.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/parser/Tokens.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/tree/TreeInfo.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java	Wed Jun 20 13:23:26 2012 -0700
     1.2 +++ b/src/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java	Thu Jun 21 13:22:21 2012 -0700
     1.3 @@ -780,6 +780,10 @@
     1.4              return null;
     1.5          }
     1.6  
     1.7 +        public int getSourcePos(int pos) {
     1.8 +            return -1;
     1.9 +        }
    1.10 +
    1.11          public CommentStyle getStyle() {
    1.12              return cs;
    1.13          }
     2.1 --- a/src/share/classes/com/sun/tools/javac/parser/JavadocTokenizer.java	Wed Jun 20 13:23:26 2012 -0700
     2.2 +++ b/src/share/classes/com/sun/tools/javac/parser/JavadocTokenizer.java	Thu Jun 21 13:22:21 2012 -0700
     2.3 @@ -1,5 +1,5 @@
     2.4  /*
     2.5 - * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
     2.6 + * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
     2.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     2.8   *
     2.9   * This code is free software; you can redistribute it and/or modify it
    2.10 @@ -62,19 +62,54 @@
    2.11      @Override
    2.12      protected Comment processComment(int pos, int endPos, CommentStyle style) {
    2.13          char[] buf = reader.getRawCharacters(pos, endPos);
    2.14 -        return new JavadocComment(new ColReader(fac, buf, buf.length), style);
    2.15 +        return new JavadocComment(new DocReader(fac, buf, buf.length, pos), style);
    2.16      }
    2.17  
    2.18      /**
    2.19       * This is a specialized version of UnicodeReader that keeps track of the
    2.20 -     * column position within a given character stream (used for Javadoc processing).
    2.21 +     * column position within a given character stream (used for Javadoc processing),
    2.22 +     * and which builds a table for mapping positions in the comment string to
    2.23 +     * positions in the source file.
    2.24       */
    2.25 -    static class ColReader extends UnicodeReader {
    2.26 +    static class DocReader extends UnicodeReader {
    2.27  
    2.28           int col;
    2.29 +         int startPos;
    2.30  
    2.31 -         ColReader(ScannerFactory fac, char[] input, int inputLength) {
    2.32 +         /**
    2.33 +          * A buffer for building a table for mapping positions in {@link #sbuf}
    2.34 +          * to positions in the source buffer.
    2.35 +          *
    2.36 +          * The array is organized as a series of pairs of integers: the first
    2.37 +          * number in each pair specifies a position in the comment text,
    2.38 +          * the second number in each pair specifies the corresponding position
    2.39 +          * in the source buffer. The pairs are sorted in ascending order.
    2.40 +          *
    2.41 +          * Since the mapping function is generally continuous, with successive
    2.42 +          * positions in the string corresponding to successive positions in the
    2.43 +          * source buffer, the table only needs to record discontinuities in
    2.44 +          * the mapping. The values of intermediate positions can be inferred.
    2.45 +          *
    2.46 +          * Discontinuities may occur in a number of places: when a newline
    2.47 +          * is followed by whitespace and asterisks (which are ignored),
    2.48 +          * when a tab is expanded into spaces, and when unicode escapes
    2.49 +          * are used in the source buffer.
    2.50 +          *
    2.51 +          * Thus, to find the source position of any position, p, in the comment
    2.52 +          * string, find the index, i, of the pair whose string offset
    2.53 +          * ({@code pbuf[i] }) is closest to but not greater than p. Then,
    2.54 +          * {@code sourcePos(p) = pbuf[i+1] + (p - pbuf[i]) }.
    2.55 +          */
    2.56 +         int[] pbuf = new int[128];
    2.57 +
    2.58 +         /**
    2.59 +          * The index of the next empty slot in the pbuf buffer.
    2.60 +          */
    2.61 +         int pp = 0;
    2.62 +
    2.63 +         DocReader(ScannerFactory fac, char[] input, int inputLength, int startPos) {
    2.64               super(fac, input, inputLength);
    2.65 +             this.startPos = startPos;
    2.66           }
    2.67  
    2.68           @Override
    2.69 @@ -147,19 +182,43 @@
    2.70                   break;
    2.71               }
    2.72           }
    2.73 +
    2.74 +         @Override
    2.75 +         public void putChar(char ch, boolean scan) {
    2.76 +             // At this point, bp is the position of the current character in buf,
    2.77 +             // and sp is the position in sbuf where this character will be put.
    2.78 +             // Record a new entry in pbuf if pbuf is empty or if sp and its
    2.79 +             // corresponding source position are not equidistant from the
    2.80 +             // corresponding values in the latest entry in the pbuf array.
    2.81 +             // (i.e. there is a discontinuity in the map function.)
    2.82 +             if ((pp == 0)
    2.83 +                     || (sp - pbuf[pp - 2] != (startPos + bp) - pbuf[pp - 1])) {
    2.84 +                 if (pp + 1 >= pbuf.length) {
    2.85 +                     int[] new_pbuf = new int[pbuf.length * 2];
    2.86 +                     System.arraycopy(pbuf, 0, new_pbuf, 0, pbuf.length);
    2.87 +                     pbuf = new_pbuf;
    2.88 +                 }
    2.89 +                 pbuf[pp] = sp;
    2.90 +                 pbuf[pp + 1] = startPos + bp;
    2.91 +                 pp += 2;
    2.92 +             }
    2.93 +             super.putChar(ch, scan);
    2.94 +         }
    2.95       }
    2.96  
    2.97 -     protected class JavadocComment extends JavaTokenizer.BasicComment<ColReader> {
    2.98 +     protected class JavadocComment extends JavaTokenizer.BasicComment<DocReader> {
    2.99  
   2.100          /**
   2.101          * Translated and stripped contents of doc comment
   2.102          */
   2.103          private String docComment = null;
   2.104 +        private int[] docPosns = null;
   2.105  
   2.106 -        JavadocComment(ColReader comment_reader, CommentStyle cs) {
   2.107 -            super(comment_reader, cs);
   2.108 +        JavadocComment(DocReader reader, CommentStyle cs) {
   2.109 +            super(reader, cs);
   2.110          }
   2.111  
   2.112 +        @Override
   2.113          public String getText() {
   2.114              if (!scanned && cs == CommentStyle.JAVADOC) {
   2.115                  scanDocComment();
   2.116 @@ -168,6 +227,33 @@
   2.117          }
   2.118  
   2.119          @Override
   2.120 +        public int getSourcePos(int pos) {
   2.121 +            // Binary search to find the entry for which the string index is
   2.122 +            // less than pos. Since docPosns is a list of pairs of integers
   2.123 +            // we must make sure the index is always even.
   2.124 +            // If we find an exact match for pos, the other item in the pair
   2.125 +            // gives the source pos; otherwise, compute the source position
   2.126 +            // relative to the best match found in the array.
   2.127 +            if (pos < 0 || pos >= docComment.length())
   2.128 +                throw new StringIndexOutOfBoundsException();
   2.129 +            if (docPosns == null)
   2.130 +                return -1;
   2.131 +            int start = 0;
   2.132 +            int end = docPosns.length;
   2.133 +            while (start < end - 2) {
   2.134 +                // find an even index midway between start and end
   2.135 +                int index = ((start  + end) / 4) * 2;
   2.136 +                if (docPosns[index] < pos)
   2.137 +                    start = index;
   2.138 +                else if (docPosns[index] == pos)
   2.139 +                    return docPosns[index + 1];
   2.140 +                else
   2.141 +                    end = index;
   2.142 +            }
   2.143 +            return docPosns[start + 1] + (pos - docPosns[start]);
   2.144 +        }
   2.145 +
   2.146 +        @Override
   2.147          @SuppressWarnings("fallthrough")
   2.148          protected void scanDocComment() {
   2.149               try {
   2.150 @@ -209,7 +295,8 @@
   2.151                   // whitespace, then it consumes any stars, then it
   2.152                   // puts the rest of the line into our buffer.
   2.153                   while (comment_reader.bp < comment_reader.buflen) {
   2.154 -
   2.155 +                     int begin_bp = comment_reader.bp;
   2.156 +                     char begin_ch = comment_reader.ch;
   2.157                       // The wsLoop consumes whitespace from the beginning
   2.158                       // of each line.
   2.159                   wsLoop:
   2.160 @@ -263,10 +350,10 @@
   2.161                               break outerLoop;
   2.162                           }
   2.163                       } else if (! firstLine) {
   2.164 -                         //The current line does not begin with a '*' so we will indent it.
   2.165 -                         for (int i = 1; i < comment_reader.col; i++) {
   2.166 -                             comment_reader.putChar(' ', false);
   2.167 -                         }
   2.168 +                         // The current line does not begin with a '*' so we will
   2.169 +                         // treat it as comment
   2.170 +                         comment_reader.bp = begin_bp;
   2.171 +                         comment_reader.ch = begin_ch;
   2.172                       }
   2.173                       // The textLoop processes the rest of the characters
   2.174                       // on the line, adding them to our buffer.
   2.175 @@ -334,6 +421,8 @@
   2.176  
   2.177                       // Store the text of the doc comment
   2.178                      docComment = comment_reader.chars();
   2.179 +                    docPosns = new int[comment_reader.pp];
   2.180 +                    System.arraycopy(comment_reader.pbuf, 0, docPosns, 0, docPosns.length);
   2.181                  } else {
   2.182                      docComment = "";
   2.183                  }
     3.1 --- a/src/share/classes/com/sun/tools/javac/parser/Tokens.java	Wed Jun 20 13:23:26 2012 -0700
     3.2 +++ b/src/share/classes/com/sun/tools/javac/parser/Tokens.java	Thu Jun 21 13:22:21 2012 -0700
     3.3 @@ -294,6 +294,7 @@
     3.4          }
     3.5  
     3.6          String getText();
     3.7 +        int getSourcePos(int index);
     3.8          CommentStyle getStyle();
     3.9          boolean isDeprecated();
    3.10      }
     4.1 --- a/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Wed Jun 20 13:23:26 2012 -0700
     4.2 +++ b/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Thu Jun 21 13:22:21 2012 -0700
     4.3 @@ -285,7 +285,7 @@
     4.4          DocCommentTable docComments = (tree.hasTag(JCTree.Tag.TOPLEVEL))
     4.5                  ? ((JCCompilationUnit) tree).docComments
     4.6                  : env.toplevel.docComments;
     4.7 -        return docComments.getCommentText(tree);
     4.8 +        return (docComments == null) ? null : docComments.getCommentText(tree);
     4.9      }
    4.10  
    4.11      /** The position of the first statement in a block, or the position of

mercurial