[core][most languages] Fix #4814: deprecate AbstractRule#as ctx#6586
[core][most languages] Fix #4814: deprecate AbstractRule#as ctx#6586UncleOwen wants to merge 13 commits into
Conversation
Not up to standards ⛔🔴 Issues
|
| Category | Results |
|---|---|
| Complexity | 10 medium |
🟢 Metrics 0 complexity · -2 duplication
Metric Results Complexity 0 Duplication -2
TIP This summary will be updated as you push new changes. Give us feedback
|
Compared to main: (comment created at 2026-04-24 14:46:14+00:00 for 0175d71) |
|
I had a look at the codacy report. I get that ApexCRUDViolationRule.checkForAccessibility has a very high NPath complexity. But why is this flagged as new? That was true even before these changes. (Is this maybe the first time codacy scanned this file?) |
b70a67f to
b32a3d4
Compare
|
I might do a followup PR that renames all the |
… instead of JavaVisitor. Fix all the rules in pmd-java: * Use type RuleContext instead of Object * Remove calls to AbstractRule.asCtx() * Remove casts to (RuleContext) Deprecated some methods that were accidentally public: * FieldDeclarationsShouldBeAtStartOfClassRule.visit(ASTTypeDeclaration, Object) * CyclomaticComplexityRule.visitTypeDecl(ASTTypeDeclaration, Object) * SwitchDensityRule.visitSwitchLike(ASTSwitchLike, Object)
… instead of ApexVisitor. Fix all the rules in pmd-apex: * Use type RuleContext instead of Object * Remove calls to AbstractRule.asCtx() * Remove casts to (RuleContext)
…t> instead of PlsqlVisitor. Fix all the rules in pmd-plsql: * Use type RuleContext instead of Object * Remove calls to AbstractRule.asCtx() * Remove casts to (RuleContext) Deprecated unused method AbstractPLSQLRule.visit(ExecutableCode, Object).
…nstead of VtlVisitor. Fix all the rules in pmd-velocity: * Use type RuleContext instead of Object * Remove calls to AbstractRule.asCtx()
…tead of VfVisitor. Fix all the rules in pmd-visualforce: * Use type RuleContext instead of Object * Remove calls to AbstractRule.asCtx()
…nstead of JspVisitor. Fix all the rules in pmd-jsp: * Use type RuleContext instead of Object * Remove calls to AbstractRule.asCtx()
…Context> instead of ModelicaVisitor. Fix all the rules in pmd-modelica: * Use type RuleContext instead of Object * Remove calls to AbstractRule.asCtx()
… instead of HtmlVisitor. Fix all the rules in pmd-html: * Use type RuleContext instead of Object * Remove casts to (RuleContext)
…RuleContext> instead of EcmascriptVisitor. Fix all the rules in pmd-javascript: * Use type RuleContext instead of Object * Remove calls to AbstractRule.asCtx()
b32a3d4 to
0175d71
Compare
There was a problem hiding this comment.
Thanks for starting on this!
I would have expected, that this is a API-incompatible change, but apparently it is not...
Unfortunately we first need to decide, how to fill in the generic types. Using RuleContext as the return type for the visit methods is not useful/does not make sense - and AFAIK we don't use it anywhere...
public abstract class AbstractJavaRule extends AbstractRule implements JavaVisitor<RuleContext, RuleContext> {public abstract class AbstractJavaRule<R> extends AbstractRule implements JavaVisitor<RuleContext, R> {public abstract class AbstractJavaRule extends AbstractRule implements JavaVisitor<RuleContext, ?> {- ??
After reading AbstractVisitorRule, we probably should use <RuleContext, ?>.
I might do a followup PR that renames all the RuleContext data to RuleContext ctx. But as that would increase the risk of merge conflicts, I'd like to NOT do this here.
I think, that doesn't make a difference, as you anyway tackle the lines already (to remove the cast or call to asCtx). So better do it directly in one go.
But: This PR is too big to be manageable... You already split the work into nice commits. Please create separate PRs for each language. The deprecation in core can go last.
I had a look at the codacy report. I get that ApexCRUDViolationRule.checkForAccessibility has a very high NPath complexity. But why is this flagged as new? That was true even before these changes. (Is this maybe the first time codacy scanned this file?)
I don't remember anymore why we installed codacy and why it now create PR comments. Apparently we installed in 3 years ago. I assume, they check modified files and analyse these and report anything on these files. "These issues were introduced in your commit, but outside the scope of your changes." - whatever this means...
| ### 10. Create an abstract rule class for the language | ||
| * Extend `AbstractRule` and implement the parser visitor interface for your language *(see AbstractVmRule for example)* | ||
| * Extend `AbstractRule` and implement the parser visitor interface for your language *(see AbstractVfRule for example)* | ||
| * Make sure to apply the proper type arguments. |
There was a problem hiding this comment.
| * Make sure to apply the proper type arguments. | |
| * Make sure to apply the proper type arguments for the parser visitor interface: Usually, a `RuleContext` is used as the parameter type and a unbound generic type `R` is used for the return type of each visit method. Through the RuleContext one can directly report violations in the visit methods. |
I think, keeping the return type open makes more sense than forcing to use rule context... Most rule I think don't really use the return type and either return null, return super.visit or return data (which is coincidentally the rule context).
| behavior for nodes you don’t care about. | ||
|
|
||
| ### 11. Create rules | ||
| * Rules are created by extending the abstract rule class created in step 9 *(see `EmptyForeachStmtRule` for example)* |
There was a problem hiding this comment.
| * Rules are created by extending the abstract rule class created in step 11 *(see `EmptyForeachStmtRule` for example)* |
|
|
||
| ### 11. Create rules | ||
| * Rules are created by extending the abstract rule class created in step 9 *(see `EmptyForeachStmtRule` for example)* | ||
| * Creating rules is already pretty well documented in PMD - and it’s no different for a new language, |
There was a problem hiding this comment.
We should better point to the documentation - where is it?
-> https://docs.pmd-code.org/latest/pmd_userdocs_extending_writing_java_rules.html
| public abstract class AbstractJavaRule extends AbstractRule implements JavaVisitor { | ||
| public abstract class AbstractJavaRule extends AbstractRule implements JavaVisitor<RuleContext, RuleContext> { | ||
|
|
||
| @Override | ||
| public Object visitNode(Node node, Object param) { | ||
| public RuleContext visitNode(Node node, RuleContext param) { | ||
| node.children().forEach(n -> n.acceptVisitor(this, param)); | ||
| return param; | ||
| } |
There was a problem hiding this comment.
To be decided:
Either this:
| public abstract class AbstractJavaRule extends AbstractRule implements JavaVisitor { | |
| public abstract class AbstractJavaRule extends AbstractRule implements JavaVisitor<RuleContext, RuleContext> { | |
| @Override | |
| public Object visitNode(Node node, Object param) { | |
| public RuleContext visitNode(Node node, RuleContext param) { | |
| node.children().forEach(n -> n.acceptVisitor(this, param)); | |
| return param; | |
| } | |
| public abstract class AbstractJavaRule<R> extends AbstractRule implements JavaVisitor<RuleContext, R> { | |
| @Override | |
| public R visitNode(Node node, RuleContext param) { | |
| node.children().forEach(n -> n.acceptVisitor(this, param)); | |
| return null; | |
| } |
Or, as we anyway return null in the end:
| public abstract class AbstractJavaRule extends AbstractRule implements JavaVisitor { | |
| public abstract class AbstractJavaRule extends AbstractRule implements JavaVisitor<RuleContext, RuleContext> { | |
| @Override | |
| public Object visitNode(Node node, Object param) { | |
| public RuleContext visitNode(Node node, RuleContext param) { | |
| node.children().forEach(n -> n.acceptVisitor(this, param)); | |
| return param; | |
| } | |
| public abstract class AbstractJavaRule extends AbstractRule implements JavaVisitor<RuleContext, Void> { | |
| @Override | |
| public Void visitNode(Node node, RuleContext param) { | |
| node.children().forEach(n -> n.acceptVisitor(this, param)); | |
| return null; | |
| } |
Using "Void" has the advantage, that it signals, there is nothing.
|
Now that you mention it... yes, I'm also surprised, that this isn't API-incompatible. Let's make sure this isn't a false-negative in japicmp, I'll investigate. On the generics question:: If the return value isn't used anywhere, I agree with public abstract class AbstractJavaRule extends AbstractRule implements JavaVisitor<RuleContext, Void>I just wasn't sure it wasn't used anywhere. |
|
This is definitely API breaking. When I only apply the changes from AbstractJavaRule to the current main (or what was current main before today's merges), all the Java rules stop compiling. |
Can you try to figure out, why this is not detected by japicmp? |
I will look into it. |
|
With the updated version of japicmp, this PR fails. I'll close this now. If I'm bored I might create PRs (one per language) that do as much as we can do without becoming API incompatible, so there is less to do in the future. |
|
Thank you @UncleOwen for raising siom79/japicmp#507 ! |
Describe the PR
AbstractFooRuleto implementFooVisitor<RuleContext, RuleContext>instead of justFooVisitor.Object datawithRuleContext dataAbstractRule.asCtx()(RuleContext)AbstractVisitorRule, which was already fixed.AbstractRule.asCtx()AbstractVisitorRule(see above)Related issues
Ready?
./mvnw clean verifypasses (checked automatically by github actions)