Skip to content

[java] Update rule UnnecessaryCast, make it flag any unnecessary cast#3204

Merged
oowekyala merged 60 commits into
pmd:pmd/7.0.xfrom
oowekyala:java-typeres-ctxs
Apr 26, 2021
Merged

[java] Update rule UnnecessaryCast, make it flag any unnecessary cast#3204
oowekyala merged 60 commits into
pmd:pmd/7.0.xfrom
oowekyala:java-typeres-ctxs

Conversation

@oowekyala

@oowekyala oowekyala commented Apr 8, 2021

Copy link
Copy Markdown
Member

Describe the PR

The rule has been generalized to just flag any unnecessary cast, not just those which use collections. This adds some utilities to query the context type of an expression, which I think we may use further to implement #2973. In fact this branch contains the commits for such a new rule, but I removed them and will submit a revert later.

There is one thing that is not implemented here, which is casts that help disambiguate two method overloads. This is a useful feature but would need some more work. For now all casts in a method argument are ignored.

I think this illustrates nicely how reliable the type resolution code is. To fix FPs in the later commits of the branch, the rule definition didn't have to change, only the typeres implementation. And this added precision will benefit all rules.

Related issues

Ready?

  • Added unit tests for fixed bug/feature
  • Passing all unit tests
  • Complete build ./mvnw clean verify passes (checked automatically by travis)
  • Added (in-code) documentation (if needed)
  • Document the change in the release notes

@oowekyala oowekyala added this to the 7.0.0 milestone Apr 8, 2021
@ghost

ghost commented Apr 8, 2021

Copy link
Copy Markdown
1 Warning
⚠️ Running pmdtester failed, this message is mainly used to remind the maintainers of PMD.
✅ Jolly good show.
Compared to pmd/7.0.x:
This changeset changes 0 violations,
introduces 71 new violations, 0 new errors and 0 new configuration errors,
removes 0 violations, 0 errors and 0 configuration errors.
Full report
Compared to master:
This changeset changes 9217 violations,
introduces 8404 new violations, 1 new errors and 0 new configuration errors,
removes 15871 violations, 10 errors and 2 configuration errors.
Full report
Compared to pmd/7.0.x:
This changeset changes 0 violations,
introduces 71 new violations, 0 new errors and 0 new configuration errors,
removes 0 violations, 0 errors and 0 configuration errors.
[Full report](<html>

<title>504 Gateway Time-out</title>

504 Gateway Time-out


nginx

</html>/diff1/index.html)

Compared to master:
This changeset changes 9217 violations,
introduces 8411 new violations, 1 new errors and 0 new configuration errors,
removes 15871 violations, 10 errors and 2 configuration errors.
[Full report](<html>

<title>504 Gateway Time-out</title>

504 Gateway Time-out


nginx

</html>/diff2/index.html)

Compared to pmd/7.0.x:
This changeset changes 0 violations,
introduces 73 new violations, 0 new errors and 0 new configuration errors,
removes 0 violations, 0 errors and 0 configuration errors.
Full report
Compared to master:
This changeset changes 9192 violations,
introduces 8400 new violations, 1 new errors and 0 new configuration errors,
removes 15657 violations, 10 errors and 2 configuration errors.
Full report
Compared to pmd/7.0.x:
This changeset changes 0 violations,
introduces 73 new violations, 0 new errors and 0 new configuration errors,
removes 0 violations, 0 errors and 0 configuration errors.
Full report
Compared to master:
This changeset changes 9192 violations,
introduces 8400 new violations, 1 new errors and 0 new configuration errors,
removes 15657 violations, 10 errors and 2 configuration errors.
Full report
Compared to pmd/7.0.x:
This changeset changes 0 violations,
introduces 73 new violations, 0 new errors and 0 new configuration errors,
removes 0 violations, 0 errors and 0 configuration errors.
Full report
Compared to master:
This changeset changes 9192 violations,
introduces 8400 new violations, 1 new errors and 0 new configuration errors,
removes 15657 violations, 10 errors and 2 configuration errors.
Full report
Compared to pmd/7.0.x:
This changeset changes 0 violations,
introduces 73 new violations, 0 new errors and 0 new configuration errors,
removes 0 violations, 0 errors and 0 configuration errors.
Full report
Compared to master:
This changeset changes 9192 violations,
introduces 8400 new violations, 1 new errors and 0 new configuration errors,
removes 15657 violations, 10 errors and 2 configuration errors.
Full report
Compared to pmd/7.0.x:
This changeset changes 0 violations,
introduces 73 new violations, 0 new errors and 0 new configuration errors,
removes 17 violations, 0 errors and 0 configuration errors.
Full report
Compared to master:
This changeset changes 2916 violations,
introduces 8176 new violations, 1 new errors and 0 new configuration errors,
removes 15648 violations, 10 errors and 2 configuration errors.
Full report
Compared to pmd/7.0.x:
This changeset changes 0 violations,
introduces 73 new violations, 0 new errors and 0 new configuration errors,
removes 0 violations, 0 errors and 0 configuration errors.
Full report
Compared to master:
This changeset changes 2916 violations,
introduces 8176 new violations, 1 new errors and 0 new configuration errors,
removes 15648 violations, 10 errors and 2 configuration errors.
Full report
Compared to pmd/7.0.x:
This changeset changes 0 violations,
introduces 82 new violations, 0 new errors and 0 new configuration errors,
removes 0 violations, 0 errors and 0 configuration errors.
Full report
Compared to master:
This changeset changes 2916 violations,
introduces 8185 new violations, 1 new errors and 0 new configuration errors,
removes 15648 violations, 10 errors and 2 configuration errors.
Full report
Compared to pmd/7.0.x:
This changeset changes 0 violations,
introduces 141 new violations, 0 new errors and 0 new configuration errors,
removes 0 violations, 0 errors and 0 configuration errors.
Full report
Compared to master:
This changeset changes 2916 violations,
introduces 8244 new violations, 1 new errors and 0 new configuration errors,
removes 15648 violations, 10 errors and 2 configuration errors.
Full report
Compared to pmd/7.0.x:
This changeset changes 0 violations,
introduces 83 new violations, 0 new errors and 0 new configuration errors,
removes 0 violations, 0 errors and 0 configuration errors.
Full report
Compared to master:
This changeset changes 2916 violations,
introduces 8186 new violations, 1 new errors and 0 new configuration errors,
removes 15648 violations, 10 errors and 2 configuration errors.
Full report
Compared to pmd/7.0.x:
This changeset changes 0 violations,
introduces 84 new violations, 0 new errors and 0 new configuration errors,
removes 0 violations, 0 errors and 0 configuration errors.
Full report
Compared to master:
This changeset changes 2916 violations,
introduces 8187 new violations, 1 new errors and 0 new configuration errors,
removes 15648 violations, 10 errors and 2 configuration errors.
Full report

Generated by 🚫 Danger

... and not being propagated to the enclosing site.

Inference happening in the added test:

```
Phase INVOC_STRICT     valueOf(java.lang.Class<T>, java.lang.String) -> T
    New bound           (ctx 5):   'b <: java.lang.Enum<'b>
    Context 5          valueOf(java.lang.Class<'b>, java.lang.String) -> 'b
    RETURN

    ARGUMENTS
        Checking arg 0 against java.lang.Class<'b>
            At:   /*unknown*/:16 :33..16:46
            Expr: this.enumType
            New bound           (ctx 5):   'b = T

        Checking arg 1 against java.lang.String
            At:   /*unknown*/:16 :48..16:61
            Expr: source.trim()
            Skipping instantiation of java.lang.String.trim() -> java.lang.String, it's already complete

    Ivar instantiated   (ctx 5):   'b := T
    Success: valueOf(java.lang.Class<T>, java.lang.String) -> java.lang.Enum
```

On line `new bound... 'b = T` what happens is the context will
check that the previous bound `'b <: java.lang.Enum<'b>` against
`'b = T`. Since T has upper bound `Enum`, not `Enum<T>`, an unchecked
conversion is necessary (`Enum ~> Enum<T>`). This needs to be notified
to the inference context so that invocation properly erases the return
type to `Enum`.

This was causing a FP with UnnecessaryCast, as in the previous, bugged
version, the return type of `Enum.valueOf(...)` was inferred to `T`,
 which doesn't need to be cast to `T`.
@oowekyala oowekyala linked an issue Apr 12, 2021 that may be closed by this pull request
@oowekyala oowekyala changed the title [java] Update rule UnnecessaryCast [java] Update rule UnnecessaryCast, make it flag any unnecessary cast Apr 12, 2021

@adangel adangel left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome, great work! 🎉

There is a small issue with lambdas:
https://github.com/checkstyle/checkstyle/blob/checkstyle-8.10/src/test/resources/com/puppycrawl/tools/checkstyle/grammars/InputRegressionJava8Class1.java#L61
This is reported, I think, that's correct - the cast is unnecessary here. But the violation message is Unnecessary cast ({0}). I think, it should be "Unnecessary cast (Comparator)".

Comment thread docs/pages/7_0_0_release_notes.md
Comment thread pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTExpression.java Outdated
Comment thread pmd-java/src/main/resources/category/java/codestyle.xml
@oowekyala oowekyala self-assigned this Apr 24, 2021
@oowekyala oowekyala merged commit 8d66b02 into pmd:pmd/7.0.x Apr 26, 2021
@oowekyala oowekyala deleted the java-typeres-ctxs branch April 26, 2021 11:17
@adangel adangel mentioned this pull request Jan 23, 2023
55 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[java] Generalize UnnecessaryCast to flag all unnecessary casts [java] UnnecessaryCast false positive with unchecked cast

2 participants