Skip to content
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

New Rule: IgnoredReturnValue #2698

Merged
merged 4 commits into from
May 19, 2020
Merged

Conversation

cortinico
Copy link
Member

@cortinico cortinico commented May 15, 2020

I've cherry-picked @bbaldino commits and fixed the tests for the new rule IgnoredReturnValue.

I've tried this approach that checks if a PsiElement is "isolated" and the return value is not Unit. I'm not sure it's the correct one but from the tests it seems promising.

I'd be happy to receive further ideas for test cases or improvements.

Closes #209
Closes #2239
Closes #2242

@codecov
Copy link

codecov bot commented May 15, 2020

Codecov Report

Merging #2698 into master will increase coverage by 0.04%.
The diff coverage is 87.50%.

Impacted file tree graph

@@             Coverage Diff              @@
##             master    #2698      +/-   ##
============================================
+ Coverage     79.85%   79.89%   +0.04%     
- Complexity     2305     2314       +9     
============================================
  Files           381      382       +1     
  Lines          6940     6979      +39     
  Branches       1250     1262      +12     
============================================
+ Hits           5542     5576      +34     
  Misses          779      779              
- Partials        619      624       +5     
Impacted Files Coverage Δ Complexity Δ
...arturbosch/detekt/rules/bugs/IgnoredReturnValue.kt 86.84% <86.84%> (ø) 9.00 <9.00> (?)
...sch/detekt/rules/providers/PotentialBugProvider.kt 100.00% <100.00%> (ø) 2.00 <0.00> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 2ec2d5a...c2bb657. Read the comment docs.

Copy link
Member

@schalkms schalkms left a comment

Choose a reason for hiding this comment

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

Thanks, I like this rule 🥇
Did you run this on detekt itself or any 3rd party projects in order to check for any false-positives?

Script:
https://github.com/detekt/detekt/blob/master/scripts/get_analysis_projects.groovy

Comment on lines 52 to 66
val returnType = resolvedCall.resultingDescriptor.returnType ?: return

if (returnType.isUnit()) {
return
}
Copy link
Member

@schalkms schalkms May 15, 2020

Choose a reason for hiding this comment

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

nit: then the @Suppress isn't necessary anymore.

Suggested change
val returnType = resolvedCall.resultingDescriptor.returnType ?: return
if (returnType.isUnit()) {
return
}
if (resolvedCall.resultingDescriptor.returnType?.isUnit() == true) return

Copy link
Member Author

Choose a reason for hiding this comment

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

I'd rather keep it separated to improve readability. Feel free to reopen if you think it's still needed in the following diff.

Copy link
Member

Choose a reason for hiding this comment

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

True. Maybe the code should read if (returnType?.isUnit() == true).
I just don't want to spam the codebase with Suppress annotations.

@BraisGabin
Copy link
Member

Quoting myself:

The annotation @CheckReturnValue does that more less. There was a thread about this here: #209 and there is an implementation for android lint and error-prone

You can read #2239 for more context.

But in short: I think that this rule should use the @CheckReturnValue annotation. Then we can add a flag to check for all of them.

@cortinico
Copy link
Member Author

But in short: I think that this rule should use the @CheckReturnValue annotation. Then we can add a flag to check for all of them.

Agree on this. I'll extend the rule to account only calls to functions annotated with @CheckReturnValue

@schalkms
Copy link
Member

But in short: I think that this rule should use the @CheckReturnValue annotation. Then we can add a flag to check for all of them.

I would do this in a next step and merge this PR first. It makes it also easier to review.

@BraisGabin
Copy link
Member

I would do this in a next step and merge this PR first. It makes it also easier to review.

I understand your point, but, wouldn't that delay our release? I mean, we would have no-production ready code in master.

@schalkms
Copy link
Member

The rule is disabled anyway.

@cortinico
Copy link
Member Author

cortinico commented May 18, 2020

I've posted another diff for this rule. There are still some open points that I would love to get an input from @BraisGabin @schalkms:

  • Currently the annotation are checked by simple name only (== CheckReturnValue) against CheckReturnValue and CheckResult. Should this be configurable? (imho, yes)

  • Should annotations be checked against their fully qualified name (com.google.errorprone.annotations.CheckReturnValue and androidx.annotation.CheckResult)? (imho, not necessary given how specific are those annotations).

  • Should the whole annotations requirement be configurable? Like having a restrictToAnnotatedMethods: true parameter? (imho, yes)

  • I found a false negative scenario: when the call site is the last statement of a block. Currently the rule is just ignoring this scenario. I've added a test case for that. I wasn't able to find a simple solution to this false negative, and this is probably worth a follow-up PR

@schalkms
Copy link
Member

  • Currently the annotation are checked by simple name only (== CheckReturnValue) against CheckReturnValue and CheckResult. Should this be configurable? (imho, yes)
    => yes, this could be done in a separate PR. This would be a nice improvement!

  • Should annotations be checked against their fully qualified name (com.google.errorprone.annotations.CheckReturnValue and androidx.annotation.CheckResult)? (imho, not necessary given how specific are those annotations).
    => not necessary IMHO

  • Should the whole annotations requirement be configurable? Like having a restrictToAnnotatedMethods: true parameter? (imho, yes)
    => yes, this could be done in a separate PR. This would be a nice improvement!

  • I found a false negative scenario: when the call site is the last statement of a block. Currently the rule is just ignoring this scenario. I've added a test case for that. I wasn't able to find a simple solution to this false negative, and this is probably worth a follow-up PR
    => Agreed.

HTH 🙂

@BraisGabin
Copy link
Member

* Currently the annotation are checked by simple name only (`== CheckReturnValue`) against `CheckReturnValue` and `CheckResult`. Should this be configurable? (imho, yes)

* Should annotations be checked against their fully qualified name (`com.google.errorprone.annotations.CheckReturnValue` and `androidx.annotation.CheckResult`)? (imho, not necessary given how specific are those annotations).

Yes, I think that this should be configurable, and in this configuration we can support both options. The default value should be something like['*.CheckReturnValue', '*.CheckResult']. Then it's up to the user to use fully qualified name or not. The only thing to discuess here is which type of regex do we want here. Options that I see:

  1. Full regex: Maximum flexibility, difficult to read and maintain: ['.*\.CheckReturnValue', '.*\.CheckResult']
  2. glob: No that flexible but gives a lot of flexibility: ['*.CheckReturnValue', '*.CheckResult']
  3. plain string: We just chech that the of the Annotation: ['CheckReturnValue', 'CheckResult']

The problem here is that in detekt we doesn't have a defined way to do this. I'll open an issue to talk about this. In my opinion the second option is the best. It provides a lot of flexibility and it's easy to read.

* Should the whole annotations requirement be configurable? Like having a `restrictToAnnotatedMethods: true` parameter? (imho, yes)

Yes

* I found a false negative scenario: when the call site is the last statement of a block. Currently the rule is just ignoring this scenario. I've added a test case for that. I wasn't able to find a simple solution to this false negative, and this is probably worth a follow-up PR

Agree.

@cortinico
Copy link
Member Author

cortinico commented May 18, 2020

The problem here is that in detekt we doesn't have a defined way to do this. I'll open an issue to talk about this. In my opinion the second option is the best. It provides a lot of flexibility and it's easy to read.

I'd either go for option 2 or 3. Option 2 could be achieved using this:

fun String.simplePatternToRegex(): Regex {
return this
.replace(".", "\\.")
.replace("*", ".*")
.replace("?", ".?")
.toRegex()
}

This will make the rule behavior consistent with the ForbiddenImport rule, that seems reasonable. Option 3 is definitely the easiest. Still don't know if we're maybe offering a "too flexible" solution for a scenario that users probably will never customize.

I'd be in for option 2, I just don't want to block this PR with #2711

@BraisGabin
Copy link
Member

For me the option 2 is the best. And for sure, this doesn't need to wait for #2711. That issue is a more generic one and probably something to face for 2.0.

For me this PR can be merged right now if you agree. The missing parts are just to add more configuration but the rule right now work as intended with the default configurations. So any other feature can be added in other PR.

@cortinico
Copy link
Member Author

Sure, go for that, I'll follow up with a couple of small PRs

@schalkms schalkms merged commit 63f158d into detekt:master May 19, 2020
@cortinico cortinico deleted the ignored_return_value branch May 19, 2020 09:33
@arturbosch arturbosch added this to the 1.10.0 milestone May 19, 2020
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.

New rule: Warn on ignored return value CheckReturnValue Rule
5 participants