Skip to content

Commit 122ffca

Browse files
authored
Merge pull request github#6645 from Marcono1234/marcono1234/spurious-javadoc-param-generic-class
Java: Detect spurious param Javadoc tag of generic classes
2 parents b51ce1d + 3c7b39f commit 122ffca

File tree

6 files changed

+52
-13
lines changed

6 files changed

+52
-13
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
lgtm,codescanning
2+
* The query `java/unknown-javadoc-parameter` now raises alerts for type parameters of generic classes that are documented but don't exist (perhaps due to using the wrong syntax, e.g. `@param T` instead of `@param <T>`).

java/ql/src/Advisory/Documentation/SpuriousJavadocParam.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ public void html(int ordinate){ ... }
3939
*/
4040
public <T> void parameterized(T parameter){ ... }
4141

42+
/**
43+
* BAD: The following param tag refers to a non-existent type parameter.
44+
*
45+
* @param <X> The type of the elements.
46+
*/
47+
class Generic<T> { ...}
4248

4349
/**
4450
* GOOD: A proper Javadoc comment.

java/ql/src/Advisory/Documentation/SpuriousJavadocParam.qhelp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@
66

77
<overview>
88
<p>
9-
Javadoc comments for public methods and constructors should use the <code>@param</code> tag to describe the available
10-
parameters. If the comment includes any empty, incorrect or outdated parameter names then this will make
9+
Javadoc comments for public methods, constructors and generic classes should use the <code>@param</code> tag to describe the available
10+
parameters and type parameters. If the comment includes any empty, incorrect or outdated parameter names then this will make
1111
the documentation more difficult to read.
1212
</p>
1313

1414
</overview>
1515
<recommendation>
1616

17-
<p>The Javadoc comment for a method or constructor should always use non-empty <code>@param</code> values that match actual parameter or type parameter names.</p>
17+
<p>The Javadoc comment for a method, constructor or generic class should always use non-empty <code>@param</code> values that match actual parameter or type parameter names.</p>
1818

1919
</recommendation>
2020
<example>

java/ql/src/Advisory/Documentation/SpuriousJavadocParam.ql

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/**
22
* @name Spurious Javadoc @param tags
3-
* @description Javadoc @param tags that do not match any parameters in the method or constructor are confusing.
3+
* @description Javadoc @param tags that do not match any parameters in the method or constructor or
4+
* any type parameters of the annotated class are confusing.
45
* @kind problem
56
* @problem.severity recommendation
67
* @precision very-high
@@ -10,21 +11,33 @@
1011

1112
import java
1213

13-
from Callable callable, ParamTag paramTag, string what, string msg
14+
from Documentable documentable, ParamTag paramTag, string msg
1415
where
15-
callable.(Documentable).getJavadoc().getAChild() = paramTag and
16-
(if callable instanceof Constructor then what = "constructor" else what = "method") and
16+
documentable.getJavadoc().getAChild() = paramTag and
1717
if exists(paramTag.getParamName())
1818
then
19-
// The tag's value is neither matched by a callable parameter name ...
20-
not callable.getAParameter().getName() = paramTag.getParamName() and
21-
// ... nor by a type parameter name.
22-
not exists(TypeVariable tv | tv.getGenericCallable() = callable |
19+
documentable instanceof Callable and
20+
exists(string what |
21+
if documentable instanceof Constructor then what = "constructor" else what = "method"
22+
|
23+
// The tag's value is neither matched by a callable parameter name ...
24+
not documentable.(Callable).getAParameter().getName() = paramTag.getParamName() and
25+
// ... nor by a type parameter name.
26+
not exists(TypeVariable tv | tv.getGenericCallable() = documentable |
27+
"<" + tv.getName() + ">" = paramTag.getParamName()
28+
) and
29+
msg =
30+
"@param tag \"" + paramTag.getParamName() + "\" does not match any actual parameter of " +
31+
what + " \"" + documentable.getName() + "()\"."
32+
)
33+
or
34+
documentable instanceof ClassOrInterface and
35+
not exists(TypeVariable tv | tv.getGenericType() = documentable |
2336
"<" + tv.getName() + ">" = paramTag.getParamName()
2437
) and
2538
msg =
26-
"@param tag \"" + paramTag.getParamName() + "\" does not match any actual parameter of " +
27-
what + " \"" + callable.getName() + "()\"."
39+
"@param tag \"" + paramTag.getParamName() +
40+
"\" does not match any actual type parameter of type \"" + documentable.getName() + "\"."
2841
else
2942
// The tag has no value at all.
3043
msg = "This @param tag does not have a value."

java/ql/test/query-tests/SpuriousJavadocParam/Test.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,4 +105,18 @@ class SomeClass {
105105
*/
106106
SomeClass(int i, int j) {}
107107
}
108+
109+
/**
110+
* @param <T> exists
111+
* @param T wrong syntax
112+
* @param <X> does not exist
113+
*/
114+
class GenericClass<T> {}
115+
116+
/**
117+
* @param <T> exists
118+
* @param T wrong syntax
119+
* @param <X> does not exist
120+
*/
121+
interface GenericInterface<T> {}
108122
}

java/ql/test/query-tests/SpuriousJavadocParam/test.expected

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,7 @@
88
| Test.java:91:6:91:12 | @param | This @param tag does not have a value. |
99
| Test.java:97:6:97:12 | @param | This @param tag does not have a value. |
1010
| Test.java:104:8:104:14 | @param | @param tag "k" does not match any actual parameter of constructor "SomeClass()". |
11+
| Test.java:111:6:111:12 | @param | @param tag "T" does not match any actual type parameter of type "GenericClass". |
12+
| Test.java:112:6:112:12 | @param | @param tag "<X>" does not match any actual type parameter of type "GenericClass". |
13+
| Test.java:118:6:118:12 | @param | @param tag "T" does not match any actual type parameter of type "GenericInterface". |
14+
| Test.java:119:6:119:12 | @param | @param tag "<X>" does not match any actual type parameter of type "GenericInterface". |

0 commit comments

Comments
 (0)