-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[apex] Add validation of ApexDoc comments #1314
Conversation
@@ -8,4 +8,23 @@ | |||
<description> | |||
Rules that are related to code documentation. | |||
</description> | |||
|
|||
<rule name="ApexDoc" | |||
since="9.9.9" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which version?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At the time, the next release would be 6.7.0
<properties> | ||
<!-- relevant for Code Climate output only --> | ||
<property name="cc_categories" value="Style" /> | ||
<property name="cc_remediation_points_multiplier" value="50" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What should the multiplier be?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See here for explanation of remediation points: https://github.com/codeclimate/spec/blob/master/SPEC.md#remediation-points
In the implementation of our CodeClimateRenderer, we use the baseline of 50_000 (which is the estimated required time for a trivial fix) and multiply it with the property defined here: https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/renderers/CodeClimateRenderer.java#L124-L132
I see, that we use multipliers between 1 and 250. Fixing missing documentation can be time consuming and we provide here a rough guess across all types of missing doc (class documentation might take more effort than a property documentation).
IMHO, 50 sounds like a reasonable value to me.
Generated by 🚫 Danger |
@jeffhube thanks for the contribution. This is a very interesting approach to rebuilding comment info from source, I didn't realize we had that The approach however seems not very extensible (having the rule parse everything and find comments), so we should probably analyze these very interesting ideas you bring and see if we can work out a more extensible approach. Let us ponder a few days on this and come back to you with our thoughts. |
I've been thinking about this, and I believe we should move the parsing to Doing so would require:
Once that's done, the rule could be updated to simply visiting the nodes that require doc, and transversing the tree to look for those nodes without parsing. |
Here is where I am at so far:
Construction of
|
@jeffhube I'm impressed by your progress so far! Thanks for being so awesome.
yes! definitely! We want the tree to mirror the code as much as possible! One more thing I've just noticed, you seem to assume any previous formal comment belongs to a given class / method / property / etc. So in an example such as: /**
* Some comment
*/
public with sharing class Simple {
public String someParam { get; set; }
public void getInit() {
someParam = "test";
}
} All 3, the class, the property AND the method will have an |
Thanks, @jsotuyod ! I've fixed the outstanding items I mentioned above. The I've not been able to reproduce the issue you mentioned. Looking at that code snippet in the designer, I only see a single comment node, parented to the class. That case should also be covered by unit tests like this one: <test-code>
<description>public method should have comment</description>
<expected-problems>1</expected-problems>
<code><![CDATA[
/**
* @description Foo
*/
public class Foo {
public void bar() { }
}
]]></code>
</test-code> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Amazing!
I've just a few minor things, but we can fix them upon merge.
This looks ready, WDYT @jsotuyod ?
return null; | ||
} | ||
|
||
private class ApexDocComment { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be a private static class
@@ -8,4 +8,23 @@ | |||
<description> | |||
Rules that are related to code documentation. | |||
</description> | |||
|
|||
<rule name="ApexDoc" | |||
since="6.7.0" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is by now 6.8.0 😄
<properties> | ||
<!-- relevant for Code Climate output only --> | ||
<property name="cc_categories" value="Style" /> | ||
<property name="cc_remediation_points_multiplier" value="50" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See here for explanation of remediation points: https://github.com/codeclimate/spec/blob/master/SPEC.md#remediation-points
In the implementation of our CodeClimateRenderer, we use the baseline of 50_000 (which is the estimated required time for a trivial fix) and multiply it with the property defined here: https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/renderers/CodeClimateRenderer.java#L124-L132
I see, that we use multipliers between 1 and 250. Fixing missing documentation can be time consuming and we provide here a rough guess across all types of missing doc (class documentation might take more effort than a property documentation).
IMHO, 50 sounds like a reasonable value to me.
super(klass.hashCode()); | ||
} | ||
|
||
public void calculateLineNumbers(SourceCodePositioner positioner, int startOffset, int endOffset) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method should not be public - it's enough, if it can be called from classes within the same package (net.sourceforge.pmd.lang.apex.ast
).
class="net.sourceforge.pmd.lang.apex.rule.documentation.ApexDocRule" | ||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_documentation.html#apexdoc"> | ||
<description> | ||
Identifies missing or incorrect ApexDoc comments. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should enhance the description from your PR description:
This rule validates that:
- ApexDoc comments are present for classes, methods, and properties that are public or global, excluding
overrides and test classes (as well as the contents of test classes).- ApexDoc comments should contain
@description
.- ApexDoc comments on non-void, non-constructor methods should contain
@return
.- ApexDoc comments on void or constructor methods should not contain
@return
.- ApexDoc comments on methods with parameters should contain
@param
for each parameter, in the same
order as the method signature.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll edit when I merge.
} | ||
|
||
public AbstractApexNodeBase(Class<?> klass) { | ||
super(klass.hashCode()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
all instances of a node type using this constructor would have the same id.. I'm not sure it would affect our current use, but maybe we should avoid this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nevermind, we already did it this way.. to be revised in a different PR
private TokenLocation getApexDocTokenLocation(int index) { | ||
TokenLocation last = null; | ||
for (TokenLocation location : tokenLocations) { | ||
if (location.index >= index) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the tokenLocations
list is sorted, we can probably be smarter about this search
ApexLexer lexer = new ApexLexer(stream); | ||
|
||
ArrayList<TokenLocation> tokenLocations = new ArrayList<>(); | ||
Integer startIndex = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be a primitive
ArrayList<TokenLocation> tokenLocations = new ArrayList<>(); | ||
Integer startIndex = 0; | ||
Token token = lexer.nextToken(); | ||
Integer endIndex = lexer.getCharIndex(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be a primitive
@Override | ||
public Object visit(ASTAnnotation node, Object data) { | ||
if (node.getImage().equals("IsTest")) { | ||
inTestClass = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also, this variable is never being reset
Merged! Thanks @jeffhube for the amazing job! I fixed all comments and reworked the parsing a little...
This will be part of PMD 6.8.0. The groundwork for #1087 is now in place, I left a TODO there. Thanks again for the contribution! |
Please, prefix the PR title with the language it applies to within brackets, such as [java] or [apex]. If not specific to a language, you can use [core]
Before submitting a PR, please check that:
master
. The PMD team will merge back to support branches as needed../mvnw test
passes../mvnw pmd:check
passes../mvnw checkstyle:check
passes. Check this for more infoPR Description:
This rule validates that:
@description
.@return
.@return
.@param
for each parameter, in the same order as the method signature.Since comments are not present in the AST, this rule expects the ApexDoc comment to be the first non-whitespace token that starts above the line containing either the first annotation if present, otherwise the class/method/property name (since that is considered to be the start of the class/method/property node). This does require the source code in string form, which I am capturing in ApexRootNode, and also tokenizing in the rule using ApexLexer. Suggestions of better ways to handle this are welcome.
Finds ApexDoc Comment:
Does not find ApexDoc comment: