Bug 561139 - [14] Report missing param tag for component of record
- add logic to Javadoc.resolveTypeParameterTags to handle record
parameters to add checking for duplicates, missing tags, and
invalid param tags
- add tests to JavadocTestForRecord
Change-Id: I59c4c66b5f437f85b18a5524b173679400364f46
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocTestForRecord.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocTestForRecord.java
index b1f5219..4d56617 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocTestForRecord.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocTestForRecord.java
@@ -33,6 +33,8 @@
String docCommentSupport = CompilerOptions.ENABLED;
String reportInvalidJavadoc = CompilerOptions.ERROR;
+ String reportInvalidJavadocTags = CompilerOptions.ENABLED;
+ String reportInavlidJavadocTagsVisibility = CompilerOptions.PRIVATE;
String reportInvalidJavadocVisibility = CompilerOptions.PRIVATE;
String reportMissingJavadocTags = CompilerOptions.ERROR;
String reportMissingJavadocTagsOverriding = CompilerOptions.ENABLED;
@@ -83,6 +85,8 @@
}
if (this.reportMissingJavadocComments != null)
options.put(CompilerOptions.OPTION_ReportMissingJavadocComments, this.reportMissingJavadocComments);
+ options.put(CompilerOptions.OPTION_ReportInvalidJavadocTags, this.reportInvalidJavadocTags);
+ options.put(CompilerOptions.OPTION_ReportInvalidJavadocTagsVisibility, this.reportInavlidJavadocTagsVisibility);
options.put(CompilerOptions.OPTION_ReportFieldHiding, CompilerOptions.IGNORE);
options.put(CompilerOptions.OPTION_ReportSyntheticAccessEmulation, CompilerOptions.IGNORE);
options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.ERROR);
@@ -129,6 +133,8 @@
super.setUp();
this.docCommentSupport = CompilerOptions.ENABLED;
this.reportInvalidJavadoc = CompilerOptions.ERROR;
+ this.reportInvalidJavadocTags = CompilerOptions.ENABLED;
+ this.reportInvalidJavadocVisibility = CompilerOptions.PRIVATE;
this.reportInvalidJavadocVisibility = CompilerOptions.PRIVATE;
this.reportMissingJavadocTags = CompilerOptions.ERROR;
this.reportMissingJavadocComments = CompilerOptions.ERROR;
@@ -170,4 +176,98 @@
"0");
}
+ public void test004() {
+ if(this.complianceLevel < ClassFileConstants.JDK14) {
+ return;
+ }
+ runConformTest(new String[] { "X.java",
+ " /** \n" +
+ " * @param a\n" +
+ " */ \n" +
+ " public record X(int a) {\n" +
+ " /** \n" +
+ " * @param args \n" + " */ \n" +
+ " public static void main(String[] args){\n" +
+ " System.out.println(0);\n" +
+ " }\n" +
+ " }" },
+ "0");
+ }
+
+ public void test005() {
+ if(this.complianceLevel < ClassFileConstants.JDK14) {
+ return;
+ }
+ runNegativeTest(new String[] { "X.java",
+ " /** \n" +
+ " */ \n" +
+ " public record X(int a) {\n" +
+ " /** \n" +
+ " * @param args \n" +
+ " */ \n" +
+ " public static void main(String[] args){\n" +
+ " System.out.println(0);\n" +
+ " }\n" +
+ " }" },
+ "----------\n" +
+ "1. ERROR in X.java (at line 3)\n" +
+ " public record X(int a) {\n" +
+ " ^\n" +
+ "Javadoc: Missing tag for parameter a\n" +
+ "----------\n",
+ JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
+ }
+
+ public void test006() {
+ if(this.complianceLevel < ClassFileConstants.JDK14) {
+ return;
+ }
+ runNegativeTest(new String[] { "X.java",
+ " /** \n" +
+ " * @param a\n" +
+ " * @param a\n" +
+ " */ \n" +
+ " public record X(int a) {\n" +
+ " /** \n" +
+ " * @param args \n" +
+ " */ \n" +
+ " public static void main(String[] args){\n" +
+ " System.out.println(0);\n" +
+ " }\n" +
+ " }" },
+ "----------\n" +
+ "1. ERROR in X.java (at line 3)\n" +
+ " * @param a\n" +
+ " ^\n" +
+ "Javadoc: Duplicate tag for parameter\n" +
+ "----------\n",
+ JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
+ }
+
+ public void test007() {
+ if(this.complianceLevel < ClassFileConstants.JDK14) {
+ return;
+ }
+ runNegativeTest(new String[] { "X.java",
+ " /** \n" +
+ " * @param a\n" +
+ " * @param b\n" +
+ " */ \n" +
+ " public record X(int a) {\n" +
+ " /** \n" +
+ " * @param args \n" +
+ " */ \n" +
+ " public static void main(String[] args){\n" +
+ " System.out.println(0);\n" +
+ " }\n" +
+ " }" },
+ "----------\n" +
+ "1. ERROR in X.java (at line 3)\n" +
+ " * @param b\n" +
+ " ^\n" +
+ "Javadoc: Invalid param tag name\n" +
+ "----------\n",
+ JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
+ }
+
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java
index f4a013c..63939ca 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java
@@ -735,10 +735,12 @@
*/
private void resolveTypeParameterTags(Scope scope, boolean reportMissing) {
int paramTypeParamLength = this.paramTypeParameters == null ? 0 : this.paramTypeParameters.length;
+ int paramReferencesLength = this.paramReferences == null ? 0 : this.paramReferences.length;
// Get declaration infos
TypeParameter[] parameters = null;
TypeVariableBinding[] typeVariables = null;
+ Argument[] recordParameters = null;
int modifiers = -1;
switch (scope.kind) {
case Scope.METHOD_SCOPE:
@@ -760,11 +762,16 @@
parameters = typeDeclaration.typeParameters;
typeVariables = typeDeclaration.binding.typeVariables;
modifiers = typeDeclaration.binding.modifiers;
+ if (typeDeclaration instanceof RecordDeclaration) {
+ RecordDeclaration recordDecl = (RecordDeclaration)typeDeclaration;
+ recordParameters = recordDecl.getArgs();
+ }
break;
}
// If no type variables then report a problem for each param type parameter tag
- if (typeVariables == null || typeVariables.length == 0) {
+ if ((recordParameters == null || recordParameters.length == 0)
+ && (typeVariables == null || typeVariables.length == 0)) {
for (int i = 0; i < paramTypeParamLength; i++) {
JavadocSingleTypeReference param = this.paramTypeParameters[i];
scope.problemReporter().javadocUnexpectedTag(param.tagSourceStart, param.tagSourceEnd);
@@ -772,6 +779,70 @@
return;
}
+ // If no param tags then report a problem for each record parameter
+ if (recordParameters != null) {
+ reportMissing = reportMissing && scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5;
+ int recordParametersLength = recordParameters.length;
+ String argNames[] = new String[paramReferencesLength];
+ if (paramReferencesLength == 0) {
+ if (reportMissing) {
+ for (int i = 0, l=recordParametersLength; i<l; i++) {
+ scope.problemReporter().javadocMissingParamTag(recordParameters[i].name, recordParameters[i].sourceStart, recordParameters[i].sourceEnd, modifiers);
+ }
+ }
+ } else {
+ // Otherwise verify that all param tags match record args
+ // Scan all @param tags
+ for (int i = 0; i < paramReferencesLength; ++i) {
+ JavadocSingleNameReference param = this.paramReferences[i];
+ String paramName = new String(param.getName()[0]);
+ // Verify duplicated tags
+ boolean duplicate = false;
+ for (int j = 0; j < i && !duplicate; j++) {
+ if (paramName.equals(argNames[j])) {
+ scope.problemReporter().javadocDuplicatedParamTag(param.token, param.sourceStart, param.sourceEnd, modifiers);
+ duplicate = true;
+ }
+ }
+ if (!duplicate) {
+ argNames[i] = paramName;
+ }
+ }
+ // Look for undocumented arguments
+ if (reportMissing) {
+ for (int i = 0; i < recordParameters.length; i++) {
+ Argument arg = recordParameters[i];
+ boolean found = false;
+ for (int j = 0; j < paramReferencesLength && !found; j++) {
+ JavadocSingleNameReference param = this.paramReferences[j];
+ String paramName = new String(param.getName()[0]);
+ if (paramName.equals(new String(arg.name))) {
+ found = true;
+ }
+ }
+ if (!found) {
+ scope.problemReporter().javadocMissingParamTag(arg.name, arg.sourceStart, arg.sourceEnd, modifiers);
+ }
+ }
+ }
+ // Look for param tags that specify non-existent arguments
+ for (int i = 0; i < paramReferencesLength; i++) {
+ JavadocSingleNameReference param = this.paramReferences[i];
+ String paramName = new String(param.getName()[0]);
+ boolean found = false;
+ for (int j = 0; j < recordParameters.length; j++) {
+ Argument arg = recordParameters[j];
+ if (paramName.equals(new String(arg.name))) {
+ found = true;
+ }
+ }
+ if (!found) {
+ scope.problemReporter().javadocInvalidParamTagName(param.sourceStart, param.sourceEnd);
+ }
+ }
+ }
+ }
+
// If no param tags then report a problem for each declaration type parameter
if (parameters != null) {
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=324850, avoid secondary errors when <= 1.4