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

Add style rule for mandatory braces in for loop bodies #2658

Merged
merged 11 commits into from
May 8, 2020

Conversation

daphil19
Copy link
Contributor

@daphil19 daphil19 commented May 7, 2020

This PR closes #2652

Extracted the description inside of 'MandatoryBracesIfStatements' to a
constant to match the structure of 'MandatoryBracesForLoops'.

Refactored the helper functions in 'MandatoryBracesIfStatements' to be
extention functions, again similar to 'MandatoryBracesForLoops'.

Refactored extension functions in both to explicitly use this to help
make clear the properties of the receiver.
'MandatoryBracesIfStatements' and 'MandatoryBracesForloops' were not in
alphabetical order.
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 for tackling this and the nice 1st contribution!
The refactoring looks good.
The rule could finally be improved to also lint while loops and more tests.

}
"""

assertThat(subject.lint(code)).isEmpty()
Copy link
Member

Choose a reason for hiding this comment

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

Please use the newer API. This allows to verify the correctness of given code snippets with the help of the Kotlin compiler.

Suggested change
assertThat(subject.lint(code)).isEmpty()
assertThat(subject.compileAndLint(code)).isEmpty()

assertThat(subject.lint(code)).isEmpty()
}

it("does report multi-line without braces") {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
it("does report multi-line without braces") {
it("reports multi-line without braces") {

* for (i in 0..10) println(i)
* </compliant>
*/
class MandatoryBracesForLoops(config: Config = Config.empty) : Rule(config) {
Copy link
Member

@schalkms schalkms May 7, 2020

Choose a reason for hiding this comment

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

It would make sense to also lint while loops. This adds further value to this rule.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should that be a configuration item for this rule? Or should it be added as an additional rule?

Copy link
Member

Choose a reason for hiding this comment

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

There's no need for a configuration option here. Why would you want to have this rule enforced only for while but not for for loops? It makes very little sense.
Thus, the rule should flag both while and for loops.

import org.spekframework.spek2.Spek
import org.spekframework.spek2.style.specification.describe

class MandatoryBracesForLoopsSpec : Spek({
Copy link
Member

Choose a reason for hiding this comment

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

The spec should contain more tests with edge cases.

  • Nested loops (with and without braces)
  • for with if-else (with and without braces)

@BraisGabin
Copy link
Member

Can you add the test for for (a in b) println(a) this should not be flagged.

@daphil19
Copy link
Contributor Author

daphil19 commented May 8, 2020

Can you add the test for for (a in b) println(a) this should not be flagged.

I think that the test case starting at line 25 in the Spek file covers this, right?

@BraisGabin
Copy link
Member

Ups! I didn't see that one 👍🏻

This change addresses some of the commends in PR detekt#2658.
These tests were mainly edge cases that were requested in PR detekt#2658.

While writing these tests, the actual MandatoryBracesForLoops rule was
modified to add the apporpirate call to `super` in order to handle the
nested loop case
The rule now checks for braces in both for and while loops.

This commit also added unit tests for the while loop portion.
Because the rule now supports both for and while loops, the rule should
be renamed from MandatoryBracesForLoops to MandatoryBracesLoops.
@codecov
Copy link

codecov bot commented May 8, 2020

Codecov Report

Merging #2658 into master will decrease coverage by 0.02%.
The diff coverage is 69.56%.

Impacted file tree graph

@@             Coverage Diff              @@
##             master    #2658      +/-   ##
============================================
- Coverage     80.00%   79.97%   -0.03%     
- Complexity     2292     2303      +11     
============================================
  Files           379      380       +1     
  Lines          6761     6771      +10     
  Branches       1222     1225       +3     
============================================
+ Hits           5409     5415       +6     
  Misses          740      740              
- Partials        612      616       +4     
Impacted Files Coverage Δ Complexity Δ
...ules/style/optional/MandatoryBracesIfStatements.kt 64.28% <66.66%> (-7.94%) 14.00 <14.00> (ø)
...etekt/rules/style/optional/MandatoryBracesLoops.kt 69.23% <69.23%> (ø) 11.00 <11.00> (?)
...bosch/detekt/rules/providers/StyleGuideProvider.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 57e745b...7bf1f36. Read the comment docs.

One of the while loop tests referenced a var that wasn't present.
Comment on lines 141 to 150
fun test() {
// because if statements are expressions, this code properly prints "Odd" and "Even"
for (i in 0..10)
if (i % 2 == 0) {
println("Odd")
} else {
println("Even")
}
}
"""
Copy link
Member

Choose a reason for hiding this comment

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

What happens if you write code like this. Is the violation reported?

if (i % 2 == 0)
  for (i in 0..10)
    println(i)
else {
  println("Even")
}

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.

Looks good! I have another beneficial test case in my mind. After that I'll merge this with a smile on my face. 🙂

What happens if you write code like this. Is the violation reported?

if (i % 2 == 0)
  for (i in 0..10)
    println(i)
else {
  println("Even")
}

@schalkms schalkms merged commit 1288153 into detekt:master May 8, 2020
@arturbosch arturbosch added this to the 1.8.1 milestone May 10, 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.

Rule: Mandatory braces for single-line for loop bodies
4 participants