Thu, 21 Jun 2012 13:22:21 -0700
7178297: provide mapping from doc comment position to source file position
Reviewed-by: mcimadamore, ksrini
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