4343import com .sun .tools .javac .tree .DCTree .DCText ;
4444import com .sun .tools .javac .tree .DocTreeMaker ;
4545import com .sun .tools .javac .util .DiagnosticSource ;
46+ import com .sun .tools .javac .util .JCDiagnostic ;
4647import com .sun .tools .javac .util .List ;
4748import com .sun .tools .javac .util .ListBuffer ;
4849import com .sun .tools .javac .util .Name ;
6263public class DocCommentParser {
6364 static class ParseException extends Exception {
6465 private static final long serialVersionUID = 0 ;
66+ final int pos ;
67+
6568 ParseException (String key ) {
69+ this (Position .NOPOS , key );
70+ }
71+ ParseException (int pos , String key ) {
6672 super (key );
73+ this .pos = pos ;
6774 }
6875 }
6976
70- private enum Phase {PREAMBLE , BODY , POSTAMBLE }
77+ private enum Phase { PREAMBLE , BODY , POSTAMBLE }
7178
7279 private final ParserFactory fac ;
80+ private final JCDiagnostic .Factory diags ;
7381 private final DiagnosticSource diagSource ;
7482 private final Comment comment ;
7583 private final DocTreeMaker m ;
@@ -96,6 +104,7 @@ private enum Phase {PREAMBLE, BODY, POSTAMBLE}
96104 public DocCommentParser (ParserFactory fac , DiagnosticSource diagSource ,
97105 Comment comment , boolean isFileContent ) {
98106 this .fac = fac ;
107+ this .diags = fac .log .diags ;
99108 this .diagSource = diagSource ;
100109 this .comment = comment ;
101110 names = fac .names ;
@@ -126,18 +135,13 @@ public DCDocComment parse() {
126135 List <DCTree > tags = blockTags ();
127136 List <DCTree > postamble = isFileContent ? blockContent (Phase .POSTAMBLE ) : List .nil ();
128137
129- int pos = Position .NOPOS ;
130- if (!preamble .isEmpty ())
131- pos = preamble .head .pos ;
132- else if (!body .isEmpty ())
133- pos = body .head .pos ;
134- else if (!tags .isEmpty ())
135- pos = tags .head .pos ;
136- else if (!postamble .isEmpty ())
137- pos = postamble .head .pos ;
138-
139- DCDocComment dc = m .at (pos ).newDocCommentTree (comment , body , tags , preamble , postamble );
140- return dc ;
138+ int pos = !preamble .isEmpty () ? preamble .head .pos
139+ : !body .isEmpty () ? body .head .pos
140+ : !tags .isEmpty () ? tags .head .pos
141+ : !postamble .isEmpty () ? postamble .head .pos
142+ : 0 ;
143+
144+ return m .at (pos ).newDocCommentTree (comment , body , tags , preamble , postamble );
141145 }
142146
143147 void nextChar () {
@@ -281,7 +285,7 @@ protected DCTree blockTag() {
281285 return erroneous ("dc.no.tag.name" , p );
282286 } catch (ParseException e ) {
283287 blockContent ();
284- return erroneous (e .getMessage (), p );
288+ return erroneous (e .getMessage (), p , e . pos );
285289 }
286290 }
287291
@@ -334,7 +338,7 @@ protected DCTree inlineTag() {
334338 }
335339 }
336340 } catch (ParseException e ) {
337- return erroneous (e .getMessage (), p );
341+ return erroneous (e .getMessage (), p , e . pos );
338342 }
339343 }
340344
@@ -471,18 +475,15 @@ protected DCReference reference(boolean allowMember) throws ParseException {
471475 ref .moduleName , ref .qualExpr ,
472476 ref .member , ref .paramTypes )
473477 .setEndPos (bp );
474- } catch (ReferenceParser .ParseException parseException ) {
475- throw new ParseException (parseException .getMessage ());
478+ } catch (ReferenceParser .ParseException pe ) {
479+ throw new ParseException (pos + pe . pos , pe .getMessage ());
476480 }
477481
478482 }
479483
480484 /**
481- * Read Java identifier
482- * Matching pairs of { } are skipped; the text is terminated by the first
483- * unmatched }. It is an error if the beginning of the next tag is detected.
485+ * Reads a Java identifier.
484486 */
485- @ SuppressWarnings ("fallthrough" )
486487 protected DCIdentifier identifier () throws ParseException {
487488 skipWhitespace ();
488489 int pos = bp ;
@@ -496,10 +497,9 @@ protected DCIdentifier identifier() throws ParseException {
496497 }
497498
498499 /**
499- * Read a quoted string.
500+ * Reads a quoted string.
500501 * It is an error if the beginning of the next tag is detected.
501502 */
502- @ SuppressWarnings ("fallthrough" )
503503 protected DCText quotedString () {
504504 int pos = bp ;
505505 nextChar ();
@@ -530,7 +530,7 @@ protected DCText quotedString() {
530530 }
531531
532532 /**
533- * Read a term (that is, one word).
533+ * Reads a term (that is, one word).
534534 * It is an error if the beginning of the next tag is detected.
535535 */
536536 @ SuppressWarnings ("fallthrough" )
@@ -567,7 +567,7 @@ protected DCText inlineWord() {
567567 }
568568
569569 /**
570- * Read general text content of an inline tag, including HTML entities and elements.
570+ * Reads general text content of an inline tag, including HTML entities and elements.
571571 * Matching pairs of { } are skipped; the text is terminated by the first
572572 * unmatched }. It is an error if the beginning of the next tag is detected.
573573 */
@@ -656,7 +656,7 @@ protected void entity(ListBuffer<DCTree> list) {
656656 }
657657
658658 /**
659- * Read an HTML entity.
659+ * Reads an HTML entity.
660660 * {@literal &identifier; } or {@literal &#digits; } or {@literal &#xhex-digits; }
661661 */
662662 protected DCTree entity () {
@@ -966,7 +966,33 @@ protected void addPendingText(ListBuffer<DCTree> list, int textEnd) {
966966 }
967967 }
968968
969+ /**
970+ * Creates an {@code ErroneousTree} node, for a range of text starting at a given position,
971+ * ending at the last non-whitespace character before the current position,
972+ * and with the preferred position set to the last character within that range.
973+ *
974+ * @param code the resource key for the error message
975+ * @param pos the starting position
976+ *
977+ * @return the {@code ErroneousTree} node
978+ */
969979 protected DCErroneous erroneous (String code , int pos ) {
980+ return erroneous (code , pos , Position .NOPOS );
981+ }
982+
983+ /**
984+ * Creates an {@code ErroneousTree} node, for a range of text starting at a given position,
985+ * ending at the last non-whitespace character before the current position,
986+ * and with a given preferred position.
987+ *
988+ * @param code the resource key for the error message
989+ * @param pos the starting position
990+ * @param pref the preferred position for the node, or {@code NOPOS} to use the default value
991+ * as the last character of the range
992+ *
993+ * @return the {@code ErroneousTree} node
994+ */
995+ protected DCErroneous erroneous (String code , int pos , int pref ) {
970996 int i = bp - 1 ;
971997 loop :
972998 while (i > pos ) {
@@ -981,8 +1007,14 @@ protected DCErroneous erroneous(String code, int pos) {
9811007 }
9821008 i --;
9831009 }
1010+ if (pref == Position .NOPOS ) {
1011+ pref = i ;
1012+ }
1013+ int end = i + 1 ;
9841014 textStart = -1 ;
985- return m .at (pos ).newErroneousTree (newString (pos , i + 1 ), diagSource , code );
1015+ JCDiagnostic .DiagnosticPosition dp = DCTree .createDiagnosticPosition (comment , pos , pref , end );
1016+ JCDiagnostic diag = diags .error (null , diagSource , dp , code );
1017+ return m .at (pos ).newErroneousTree (newString (pos , end ), diag ).setPrefPos (pref );
9861018 }
9871019
9881020 protected boolean isIdentifierStart (char ch ) {
@@ -1169,7 +1201,7 @@ public DCTree parse(int pos) throws ParseException {
11691201 }
11701202 inlineText (WhitespaceRetentionPolicy .REMOVE_ALL ); // skip unexpected content
11711203 nextChar ();
1172- throw new ParseException ("dc.unexpected.content" );
1204+ throw new ParseException (pos , "dc.unexpected.content" );
11731205 }
11741206 },
11751207
@@ -1226,7 +1258,7 @@ public DCTree parse(int pos) throws ParseException {
12261258 }
12271259 inlineText (WhitespaceRetentionPolicy .REMOVE_ALL ); // skip unexpected content
12281260 nextChar ();
1229- throw new ParseException ("dc.unexpected.content" );
1261+ throw new ParseException (pos , "dc.unexpected.content" );
12301262 }
12311263 },
12321264
0 commit comments