Skip to content
Permalink
Browse files
8272374: doclint should report missing "body" comments
Reviewed-by: kcr, hannesw
  • Loading branch information
jonathan-gibbons committed Aug 16, 2021
1 parent b2c272d commit ae45592d3304f50aa9e8e114416a41e7899fe37b
Showing with 270 additions and 129 deletions.
  1. +1 −1 make/modules/java.desktop/Java.gmk
  2. +11 −3 src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Checker.java
  3. +2 −0 src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/resources/doclint.properties
  4. +23 −28 test/langtools/jdk/javadoc/tool/doclint/DocLintTest.java
  5. +4 −4 test/langtools/tools/doclint/AccessTest.java
  6. +1 −1 test/langtools/tools/doclint/CustomTagTest.java
  7. +6 −3 test/langtools/tools/doclint/EmptyAuthorTest.java
  8. +3 −3 test/langtools/tools/doclint/EmptyAuthorTest.out
  9. +79 −0 test/langtools/tools/doclint/EmptyDescriptionTest.java
  10. +22 −0 test/langtools/tools/doclint/EmptyDescriptionTest.out
  11. +5 −2 test/langtools/tools/doclint/EmptyExceptionTest.java
  12. +3 −3 test/langtools/tools/doclint/EmptyExceptionTest.out
  13. +4 −1 test/langtools/tools/doclint/EmptyParamTest.java
  14. +3 −3 test/langtools/tools/doclint/EmptyParamTest.out
  15. +4 −1 test/langtools/tools/doclint/EmptyReturnTest.java
  16. +3 −4 test/langtools/tools/doclint/EmptyReturnTest.out
  17. +1 −0 test/langtools/tools/doclint/EmptySerialFieldTest.java
  18. +1 −1 test/langtools/tools/doclint/EmptySerialFieldTest.out
  19. +4 −1 test/langtools/tools/doclint/EmptySinceTest.java
  20. +3 −4 test/langtools/tools/doclint/EmptySinceTest.out
  21. +4 −1 test/langtools/tools/doclint/EmptyVersionTest.java
  22. +3 −3 test/langtools/tools/doclint/EmptyVersionTest.out
  23. +6 −2 test/langtools/tools/doclint/EndWithIdentifierTest.java
  24. +7 −7 test/langtools/tools/doclint/EndWithIdentifierTest.out
  25. +1 −1 test/langtools/tools/doclint/LambdaTest.java
  26. +2 −2 test/langtools/tools/doclint/LiteralTest.java
  27. +4 −4 test/langtools/tools/doclint/MissingParamsTest.java
  28. +1 −1 test/langtools/tools/doclint/MissingReturnTest.java
  29. +3 −3 test/langtools/tools/doclint/MissingThrowsTest.java
  30. +5 −2 test/langtools/tools/doclint/MultipleDocLintOptionsTest.java
  31. +1 −1 test/langtools/tools/doclint/MultipleDocLintOptionsTest.out
  32. +10 −1 test/langtools/tools/doclint/ReferenceTest.java
  33. +13 −13 test/langtools/tools/doclint/ReferenceTest.out
  34. +2 −2 test/langtools/tools/doclint/SyntaxTest.java
  35. +2 −2 test/langtools/tools/doclint/packageTests/bad/Test.java
  36. +1 −1 test/langtools/tools/doclint/tool/StatsTest.java
  37. +22 −20 test/langtools/tools/javac/doclint/DocLintTest.java
@@ -23,7 +23,7 @@
# questions.
#

DOCLINT += -Xdoclint:all/protected,-reference \
DOCLINT += -Xdoclint:all/protected,-reference,-missing \
'-Xdoclint/package:java.*,javax.*'
COPY += .gif .png .wav .txt .xml .css .pf
CLEAN += iio-plugin.properties cursors.properties
@@ -182,9 +182,6 @@ public Void scan(DocCommentTree tree, TreePath p) {
reportMissing("dc.missing.comment");
return null;
}



} else {
if (tree == null) {
if (isDefaultConstructor()) {
@@ -195,6 +192,17 @@ public Void scan(DocCommentTree tree, TreePath p) {
reportMissing("dc.missing.comment");
}
return null;
} else if (tree.getFirstSentence().isEmpty() && !isOverridingMethod) {
if (tree.getBlockTags().isEmpty()) {
reportMissing("dc.empty.comment");
return null;
} else {
// Don't report an empty description if the comment contains @deprecated,
// because javadoc will use the content of that tag in summary tables.
if (tree.getBlockTags().stream().allMatch(t -> t.getKind() != DocTree.Kind.DEPRECATED)) {
env.messages.report(MISSING, Kind.WARNING, tree, "dc.empty.description");
}
}
}
}

@@ -39,6 +39,8 @@ dc.bad.option = bad option: {0}
dc.bad.value.for.option = bad value for option: {0} {1}
dc.default.constructor = use of default constructor, which does not provide a comment
dc.empty = no description for @{0}
dc.empty.comment = empty comment
dc.empty.description = no initial description
dc.entity.invalid = invalid entity &{0};
dc.exception.not.thrown = exception not thrown: {0}
dc.exists.param = @param "{0}" has already been specified
@@ -32,7 +32,6 @@
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URI;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
@@ -63,25 +62,21 @@ public static void main(String... args) throws Exception {

final String code =
/* 01 */ "/** Class comment. */\n" +
/* 02 */ "public class Test { /** */ Test() { }\n" +
/* 02 */ "public class Test { /** Constructor comment. */ Test() { }\n" +
/* 03 */ " /** Method comment. */\n" +
/* 04 */ " public void method() { }\n" +
/* 05 */ "\n" +
/* 06 */ " /** Syntax < error. */\n" +
/* 07 */ """
\s private void syntaxError() { }
""" +
/* 07 */ " private void syntaxError() { }\n" +
/* 08 */ "\n" +
/* 09 */ " /** @see DoesNotExist */\n" +
/* 10 */ """
\s protected void referenceError() { }
""" +
/* 11 */ "\n" +
/* 12 */ " /** @return */\n" +
/* 13 */ """
\s public int emptyReturn() { return 0; }
""" +
/* 14 */ "}\n";
/* 09 */ " /** Description. \n" +
/* 10 */ " * @see DoesNotExist */\n" +
/* 11 */ " protected void referenceError() { }\n" +
/* 12 */ "\n" +
/* 13 */ " /** Description. \n" +
/* 14 */ " * @return */\n" +
/* 15 */ " public int emptyReturn() { return 0; }\n" +
/* 16 */ "}\n";

final String p1Code =
/* 01 */ "package p1;\n" +
@@ -103,21 +98,21 @@ public static void main(String... args) throws Exception {
private enum Message {
// doclint messages
DL_ERR6(ERROR, "Test.java:6:16: compiler.err.proc.messager: malformed HTML"),
DL_ERR9(ERROR, "Test.java:9:14: compiler.err.proc.messager: reference not found"),
DL_WRN12(WARNING, "Test.java:12:9: compiler.warn.proc.messager: no description for @return"),
DL_ERR10(ERROR, "Test.java:10:13: compiler.err.proc.messager: reference not found"),
DL_WRN14(WARNING, "Test.java:14:8: compiler.warn.proc.messager: no description for @return"),

DL_ERR_P1TEST(ERROR, "P1Test.java:3:16: compiler.err.proc.messager: malformed HTML"),
DL_ERR_P2TEST(ERROR, "P2Test.java:3:16: compiler.err.proc.messager: malformed HTML"),
DL_WARN_P1TEST(WARNING, "P1Test.java:2:8: compiler.warn.proc.messager: no comment"),
DL_WARN_P2TEST(WARNING, "P2Test.java:2:8: compiler.warn.proc.messager: no comment"),

// doclint messages when -XDrawDiagnostics is not in effect
DL_ERR9A(ERROR, "Test.java:9: error: reference not found"),
DL_WRN12A(WARNING, "Test.java:12: warning: no description for @return"),
DL_ERR10A(ERROR, "Test.java:10: error: reference not found"),
DL_WRN14A(WARNING, "Test.java:14: warning: no description for @return"),

// javadoc messages about bad content: these should only appear when doclint is disabled
JD_WRN10(WARNING, "Test.java:10: warning: Tag @see: reference not found: DoesNotExist"),
JD_WRN13(WARNING, "Test.java:13: warning: @return tag has no arguments."),
JD_WRN14(WARNING, "Test.java:14: warning: @return tag has no arguments."),

// javadoc messages for bad options
OPT_BADARG(ERROR, "error: Invalid argument for -Xdoclint option"),
@@ -156,43 +151,43 @@ void run() throws Exception {

test(List.of(htmlVersion),
Main.Result.ERROR,
EnumSet.of(Message.DL_ERR9A, Message.DL_WRN12A));
EnumSet.of(Message.DL_ERR10A, Message.DL_WRN14A));

test(List.of(htmlVersion, rawDiags),
Main.Result.ERROR,
EnumSet.of(Message.DL_ERR9, Message.DL_WRN12));
EnumSet.of(Message.DL_ERR10, Message.DL_WRN14));

// test(List.of("-Xdoclint:none"),
// Main.Result.OK,
// EnumSet.of(Message.JD_WRN10, Message.JD_WRN13));

test(List.of(htmlVersion, rawDiags, "-Xdoclint"),
Main.Result.ERROR,
EnumSet.of(Message.DL_ERR9, Message.DL_WRN12));
EnumSet.of(Message.DL_ERR10, Message.DL_WRN14));

test(List.of(htmlVersion, rawDiags, "-Xdoclint:all/public"),
Main.Result.ERROR,
EnumSet.of(Message.OPT_BADQUAL));

test(List.of(htmlVersion, rawDiags, "-Xdoclint:all", "-public"),
Main.Result.OK,
EnumSet.of(Message.DL_WRN12));
EnumSet.of(Message.DL_WRN14));

test(List.of(htmlVersion, rawDiags, "-Xdoclint:missing"),
Main.Result.OK,
EnumSet.of(Message.DL_WRN12));
EnumSet.of(Message.DL_WRN14));

test(List.of(htmlVersion, rawDiags, "-private"),
Main.Result.ERROR,
EnumSet.of(Message.DL_ERR6, Message.DL_ERR9, Message.DL_WRN12));
EnumSet.of(Message.DL_ERR6, Message.DL_ERR10, Message.DL_WRN14));

test(List.of(htmlVersion, rawDiags, "-Xdoclint:missing,syntax", "-private"),
Main.Result.ERROR,
EnumSet.of(Message.DL_ERR6, Message.DL_WRN12));
EnumSet.of(Message.DL_ERR6, Message.DL_WRN14));

test(List.of(htmlVersion, rawDiags, "-Xdoclint:reference"),
Main.Result.ERROR,
EnumSet.of(Message.DL_ERR9));
EnumSet.of(Message.DL_ERR10));

test(List.of(htmlVersion, rawDiags, "-Xdoclint:badarg"),
Main.Result.ERROR,
@@ -18,8 +18,8 @@
* @run main DocLintTester -Xmsgs:all,-syntax/private -ref AccessTest.package.out AccessTest.java
*/

/** */
public class AccessTest { /** */ AccessTest() { }
/** . */
public class AccessTest { /** . */ AccessTest() { }
/**
* public a < b
*/
@@ -41,8 +41,8 @@ void syntax_error() { }
private void private_syntax_error() { }
}

/** */
class AccessTest2 { /** */ AccessTest2() { }
/** Class comment. */
class AccessTest2 { /** Constructor comment. */ AccessTest2() { }
/**
* public a < b
*/
@@ -11,7 +11,7 @@
* @author bpatel
*/

/**
/** .
* @customTag Text for a custom tag.
* @custom.tag Text for another custom tag.
* @unknownTag Text for an unknown tag.
@@ -8,7 +8,10 @@
* @run main DocLintTester -Xmsgs:missing -ref EmptyAuthorTest.out EmptyAuthorTest.java
*/

/** @author */
/**
* .
* @author
*/
public class EmptyAuthorTest {
/** */ EmptyAuthorTest() { }
}
/** . */ EmptyAuthorTest() { }
}
@@ -1,5 +1,5 @@
EmptyAuthorTest.java:11: warning: no description for @author
/** @author */
^
EmptyAuthorTest.java:13: warning: no description for @author
* @author
^
1 warning

@@ -0,0 +1,79 @@

/*
* @test /nodynamiccopyright/
* @bug 8272374
* @summary doclint should report missing "body" comments
* @modules jdk.javadoc/jdk.javadoc.internal.doclint
* @build DocLintTester
* @run main DocLintTester -Xmsgs:-missing EmptyDescriptionTest.java
* @run main DocLintTester -Xmsgs:missing -ref EmptyDescriptionTest.out EmptyDescriptionTest.java
*/

/** . */
public class EmptyDescriptionTest {
// a default constructor triggers its own variant of "no comment"

// no comment
public int f1;

// empty comment
/** */
public int f2;

// empty description
/**
* @since 1.0
*/
public int f3;

// deprecated: no diagnostic
/**
* @deprecated do not use
*/
public int f4;

// no comment
public int m1() { return 0; }

// empty comment
/** */
public int m2() { return 0; }

// empty description
/**
* @return 0
*/
public int m3() { return 0; }

// deprecated: no diagnostic
/**
* @deprecated do not use
* @return 0
*/
public int m4() { return 0; };

/**
* A class containing overriding methods.
* Overriding methods with missing/empty comments do not generate messages
* since they are presumed to inherit descriptions as needed.
*/
public static class Nested extends EmptyDescriptionTest {
/** . */ Nested() { }

@Override
public int m1() { return 1; }

// empty comment
/** */
@Override
public int m2() { return 1; }

// empty description
/**
* @return 1
*/
@Override
public int m3() { return 1; }

}
}
@@ -0,0 +1,22 @@
EmptyDescriptionTest.java:13: warning: use of default constructor, which does not provide a comment
public class EmptyDescriptionTest {
^
EmptyDescriptionTest.java:17: warning: no comment
public int f1;
^
EmptyDescriptionTest.java:21: warning: empty comment
public int f2;
^
EmptyDescriptionTest.java:25: warning: no initial description
* @since 1.0
^
EmptyDescriptionTest.java:36: warning: no comment
public int m1() { return 0; }
^
EmptyDescriptionTest.java:40: warning: empty comment
public int m2() { return 0; }
^
EmptyDescriptionTest.java:44: warning: no initial description
* @return 0
^
7 warnings
@@ -9,7 +9,10 @@
*/

/** . */
public class EmptyExceptionTest { /** */ EmptyExceptionTest() { }
/** @exception NullPointerException */
public class EmptyExceptionTest { /** . */ EmptyExceptionTest() { }
/**
* .
* @exception NullPointerException
*/
void emptyException() throws NullPointerException { }
}
@@ -1,4 +1,4 @@
EmptyExceptionTest.java:13: warning: no description for @exception
/** @exception NullPointerException */
^
EmptyExceptionTest.java:15: warning: no description for @exception
* @exception NullPointerException
^
1 warning
@@ -10,6 +10,9 @@

/** . */
public class EmptyParamTest { /** . */ EmptyParamTest() { }
/** @param i */
/**
* .
* @param i
*/
void emptyParam(int i) { }
}
@@ -1,5 +1,5 @@
EmptyParamTest.java:13: warning: no description for @param
/** @param i */
^
EmptyParamTest.java:15: warning: no description for @param
* @param i
^
1 warning

@@ -10,6 +10,9 @@

/** . */
public class EmptyReturnTest { /** . */ EmptyReturnTest() { }
/** @return */
/**
* .
* @return
*/
int emptyReturn() { return 0; }
}
@@ -1,5 +1,4 @@
EmptyReturnTest.java:13: warning: no description for @return
/** @return */
^
EmptyReturnTest.java:15: warning: no description for @return
* @return
^
1 warning

@@ -15,6 +15,7 @@
public class EmptySerialFieldTest implements Serializable { /** . */ EmptySerialFieldTest() { }

/**
* .
* @serialField empty String
*/
private static final ObjectStreamField[] serialPersistentFields = {
Loading

1 comment on commit ae45592

@openjdk-notifier

This comment has been minimized.

Copy link

@openjdk-notifier openjdk-notifier bot commented on ae45592 Aug 16, 2021

Please sign in to comment.