8307184: Incorrect/inconsistent specification and implementation for Elements.getDocComment

Reviewed-by: vromero, jjg
This commit is contained in:
Joe Darcy 2023-08-09 21:17:10 +00:00
parent 593ba2fe47
commit c307391ab1
2 changed files with 217 additions and 6 deletions

View File

@ -283,15 +283,34 @@ public interface Elements {
* <p> A documentation comment of an element is a comment that
* begins with "{@code /**}", ends with a separate
* "<code>*&#47;</code>", and immediately precedes the element,
* ignoring white space. Therefore, a documentation comment
* ignoring white space, annotations, end-of-line-comments ({@code
* "//"} comments), and intermediate traditional comments
* (<code>"/* ... *&#47;"</code> comments) that are not doc comments.
* Therefore, a documentation comment
* contains at least three "{@code *}" characters. The text
* returned for the documentation comment is a processed form of
* the comment as it appears in source code. The leading "{@code /**}"
* and trailing "<code>*&#47;</code>" are removed. For lines
* of the comment starting after the initial "{@code /**}",
* leading white space characters are discarded as are any
* the comment as it appears in source code:
* <ul>
* <li>The leading "{@code /**}" is removed, as are any
* immediately following space characters on that line. If all the
* characters of the line are removed, it makes no contribution to
* the returned comment.
* <li>For subsequent lines
* of the doc comment starting after the initial "{@code /**}",
* if the lines start with <em>zero</em> or more whitespace characters followed by
* <em>one</em> or more "{@code *}" characters,
* those leading whitespace characters are discarded as are any
* consecutive "{@code *}" characters appearing after the white
* space or starting the line. The processed lines are then
* space or starting the line.
* Otherwise, if a line does not have a prefix of the described
* form, the entire line is retained.
* <li> The trailing "<code>*&#47;</code>" is removed. The line
* with the trailing" <code>*&#47;</code>" also undergoes leading
* space and "{@code *}" character removal as described above. If all the characters
* of the line are removed, it makes no contribution to the
* returned comment.
* </ul>
* The processed lines are then
* concatenated together (including line terminators) and
* returned.
*
@ -299,6 +318,7 @@ public interface Elements {
* @return the documentation comment of the element, or {@code null}
* if there is none
* @jls 3.6 White Space
* @jls 3.7 Comments
*/
String getDocComment(Element e);

View File

@ -0,0 +1,191 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8307184
* @summary Test basic operation of Elements.getDocComments
* @library /tools/lib /tools/javac/lib
* @build toolbox.ToolBox JavacTestingAbstractProcessor TestGetDocComments
* @compile -processor TestGetDocComments -proc:only TestGetDocComments.java
*/
import java.io.Writer;
import java.util.*;
import java.util.function.*;
import javax.annotation.processing.*;
import javax.lang.model.element.*;
import javax.lang.model.util.*;
import toolbox.ToolBox;
/**
* Test basic workings of Elements.getDocComments
*/
public class TestGetDocComments extends JavacTestingAbstractProcessor {
public boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment roundEnv) {
if (!roundEnv.processingOver()) {
boolean elementSeen = false;
for (TypeElement typeRoot : ElementFilter.typesIn(roundEnv.getRootElements()) ) {
for (Element element : typeRoot.getEnclosedElements()) {
ExpectedComment expectedComment = element.getAnnotation(ExpectedComment.class);
if (expectedComment != null ) {
elementSeen = true;
String expectedCommentStr = expectedComment.value();
String actualComment = elements.getDocComment(element);
if (!expectedCommentStr.equals(actualComment)) {
messager.printError("Unexpected doc comment found", element);
(new ToolBox()).checkEqual(expectedCommentStr.lines().toList(),
actualComment.lines().toList());
}
}
}
if (!elementSeen) {
throw new RuntimeException("No elements seen.");
}
}
}
return true;
}
@interface ExpectedComment {
String value();
}
// Basic processing of interior lines
/**
*Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
*eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
*enim ad minim veniam, quis nostrud exercitation ullamco laboris
*nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
*in reprehenderit in voluptate velit esse cillum dolore eu
*fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
*proident, sunt in culpa qui officia deserunt mollit anim id est
*laborum.
*/
@ExpectedComment("""
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
in reprehenderit in voluptate velit esse cillum dolore eu
fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est
laborum.
""")
// End-of-line-style comment
@SuppressWarnings("") // A second preceding annotation
/* Traditional comment */
private void foo() {return ;}
// Check removal of various *'s and space characters;
// use Unicode escape to test tab removal
/**
*Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
**eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
***enim ad minim veniam, quis nostrud exercitation ullamco laboris
*****nisi ut aliquip ex ea commodo consequat.
\u0009*Duis aute irure dolor in reprehenderit in voluptate velit esse
**cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat
***cupidatat non proident, sunt in culpa qui officia deserunt mollit
*anim id est laborum.
*/
@ExpectedComment("""
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat
cupidatat non proident, sunt in culpa qui officia deserunt mollit
anim id est laborum.
""")
@SuppressWarnings("") // A second preceding annotation
// End-of-line-style comment
/*
* Traditional comment over multiple lines.
*/
private void bar() {return ;}
// Spaces _after_ the space-asterisk prefix are _not_ deleted.
/**
* Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
* eiusmod tempor incididunt ut labore et dolore magna aliqua.
*/
@ExpectedComment( // Cannot used a text block here since leading spaces are removed
" Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do\n" +
" eiusmod tempor incididunt ut labore et dolore magna aliqua.\n")
private void baz() {return ;}
// Space after ** is removed, but not space before "*/"
/** Totality */
@ExpectedComment("Totality ") // No newline
private void quux() {return ;}
// Space after "**" is removed, but not trailing space later on the line
/** Totality\u0020
*/
@ExpectedComment("Totality \n")
private void corge() {return ;}
/**
* Totality */
@ExpectedComment(" Totality ") // No newline
private void grault() {return ;}
// Trailing space characters on first line
/** \u0009\u0020
* Totality
*/
@ExpectedComment(" Totality\n")
private void wombat() {return ;}
/**
*/
@ExpectedComment("") // No newline
private void empty() {return ;}
/**
* tail */
@ExpectedComment(" tail ") // No newline
private void tail() {return ;}
/**
****/
@ExpectedComment("") // No newline
private void tail2() {return ;}
// Testing of line terminators, javac implementation normalizes them:
// * newline: \u000A
// * carriage return: \u000D
// * * carriage return + newline: \u000D\u000A
/**
* Lorem\u000A\u000D\u000D\u000Aipsum
*/
@ExpectedComment(" Lorem\n\n\nipsum\n")
private void wombat2() {return ;}
}