Skip to content

ExplicitCollectionElementAccessMethod rule fixes#4201

Merged
BraisGabin merged 5 commits intodetekt:mainfrom
Whathecode:fix-4122
Oct 29, 2021
Merged

ExplicitCollectionElementAccessMethod rule fixes#4201
BraisGabin merged 5 commits intodetekt:mainfrom
Whathecode:fix-4122

Conversation

@Whathecode
Copy link
Copy Markdown
Contributor

@Whathecode Whathecode commented Oct 24, 2021

  • Fix ExplicitCollectionElementAccessMethod reports put() usages where the return value is used #4122: false positives when return values of put are used
  • Added support to recognize custom get and set operators, which furthermore lead to a more general-purpose implementation (no more elaborate type-checking).
  • The rule now also works for set, which is in fact the main use case. put is not a valid index accessor function. The reason put can be replaced with an index accessor for maps when the return value is unused is that it essentially behaves the same as set in that case.

I think the private functions operating on KtCallExpression are best moved more centrally to reusable/tested extension functions. I could not find such a place in the library. I typically don't like creating private functions that are called from a single place, but I imagine similar logic is needed, and may even have been implemented, in other rules. I expect that if these become public helper functions I could write associated unit tests, resolving the decrease in code coverage which currently seems to fail the automated check on this PR.

The updated rule found several getters in the detekt codebase, previously not detected given that they weren't of one of the expected types, which had to be be replaced by index accessors.

…thod rule

This actually simplifies code, since any get/set operator can be treated the same; no need to look up type names. `Map.put()` is a type-specific edge case, which can be replaced by `set`, and thus indexed access, when the return value is not needed.

Right now, no check is done whether the return value is use. For both `set` and `put` no code smell should be reported if this is the case.
@codecov
Copy link
Copy Markdown

codecov bot commented Oct 24, 2021

Codecov Report

Merging #4201 (93ec8fc) into main (c848341) will decrease coverage by 0.02%.
The diff coverage is 61.90%.

Impacted file tree graph

@@             Coverage Diff              @@
##               main    #4201      +/-   ##
============================================
- Coverage     84.19%   84.16%   -0.03%     
- Complexity     3233     3241       +8     
============================================
  Files           468      468              
  Lines         10185    10182       -3     
  Branches       1786     1789       +3     
============================================
- Hits           8575     8570       -5     
+ Misses          671      669       -2     
- Partials        939      943       +4     
Impacted Files Coverage Δ
...les/style/ExplicitCollectionElementAccessMethod.kt 68.96% <55.55%> (-14.37%) ⬇️
...n/io/gitlab/arturbosch/detekt/core/DetektResult.kt 92.85% <100.00%> (ø)
...urbosch/detekt/generator/collection/RuleVisitor.kt 90.52% <100.00%> (ø)
.../io/github/detekt/parser/KotlinEnvironmentUtils.kt 75.47% <100.00%> (ø)
.../kotlin/io/gitlab/arturbosch/detekt/cli/CliArgs.kt 100.00% <0.00%> (ø)
...gitlab/arturbosch/detekt/cli/ArgumentConverters.kt 75.00% <0.00%> (+5.76%) ⬆️

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 c848341...93ec8fc. Read the comment docs.

Also fixed other tests that were failing on build server.
This also includes an early out in case types can't be resolved, rather than iterating over supertypes.
Copy link
Copy Markdown
Member

@cortinico cortinico left a comment

Choose a reason for hiding this comment

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

Great work 🚀 The only thing that is needed to update is that now this rule requires type resolution to work correctly

.isEligibleCollection()

private fun isOperatorFunction(expression: KtCallExpression): Boolean {
val function = (expression.getResolvedCall(bindingContext)?.resultingDescriptor as? FunctionDescriptor)
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.

Since you're using bindingContext here, you should add a @RequiresTypeResolution to this rule + a if(bindingContext == BindingContext.EMPTY) return check at the beginning of the visit...( method.

Copy link
Copy Markdown
Contributor Author

@Whathecode Whathecode Oct 28, 2021

Choose a reason for hiding this comment

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

Done! If I understand correctly, this was missing before as well? I.e., the removed LOC right above:

        return (caller as? KtElement).getResolvedCall(bindingContext)
            ?.resultingDescriptor
            ?.returnType
            .isEligibleCollection()

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.

Done! If I understand correctly, this was missing before as well?

Yes it was a "bug" in the sense that it was a rule with a mixed behavior that we should look into fixing: #2994

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

notable changes Marker for notable changes in the changelog rules

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ExplicitCollectionElementAccessMethod reports put() usages where the return value is used

3 participants