SwiftLint icon indicating copy to clipboard operation
SwiftLint copied to clipboard

Add rule for visually pleasing formatting of long guards

Open Johennes opened this issue 6 years ago • 7 comments

New Issue Checklist

Rule Request

I'd like to suggest a rule for enforcing the style

guard
    let a = ...,
    let b = ...,
    let c = ...
else {
    return ...
}

for guard statements where the (binding) conditions don't fit into a certain line length.

  1. Why should this rule be added?

The proposed style clearly separates the condition from the body and keeps the indentation of the body consistent with the outer scope.

The currently allowed styles for long guards are

guard let a = ...,
    let b = ...,
    let c = ... else {
        return ...
}
guard let a = ...,
    let b = ...,
    let c = ... else {
    return ...
}
guard let a = ...,
      let b = ...,
      let c = ... else {
    return ...
}

The first one moves the else body in by two levels as compared to the outer scope which IMHO breaks the reading flow.

The second option has consistent indentation in the body but the condition lines following the first line have the same indentation which makes it hard to visually tell the end of the condition and the beginning of the body apart.

The last one, finally, uses an indentation for the condition lines that is not a multiple of the base indentation level in the rest of the code (here 2 spaces instead of 4) which IMHO is bad for readability as well.

  1. Provide several examples of what would and wouldn't trigger violations.

Not ok:

See above, and

---------------------------------------| Line length limit
guard let a = ..., let b = ..., let c = ... else {
    return ...
}

Ok:

---------------------------------------| Line length limit
guard let a = ..., let b = ... else {
    return ...
}
---------------------------------------| Line length limit
guard
    let a = ...,
    let b = ...,
    let c = ...
else {
    return ...
}

See above.

  1. Should the rule be configurable, if so what parameters should be configurable?

Yes, the severity level and the threshold line length.

  1. Should the rule be opt-in or enabled by default? Why?

Opt-in because not everyone might like this style.

Johennes avatar Jun 14 '18 09:06 Johennes

We'd be willing to work on a PR for this but wanted to know if such a contribution would be welcome first.

Johennes avatar Jun 14 '18 09:06 Johennes

We'd be willing to work on a PR for this but wanted to know if such a contribution would be welcome first.

Certainly!

jpsim avatar Jun 24 '18 20:06 jpsim

Hi there! My team needs this rule and, if you don't mind, I'll give it a try. I'll try to make it not conflict with existing rules, such as line_length and conditional_returns_on_newline

ornithocoder avatar Aug 19 '18 15:08 ornithocoder

My favorite style is slightly different from the proposed one:

guard let a = ...,
      let b = ...,
      let c = ...
else {
    return ...
}

Uncommon avatar Aug 20 '18 14:08 Uncommon

Curious if there have been any advances in this? I know raywenderlich.com's swift style guide has it as this:

guard 
  let number1 = number1,
  let number2 = number2,
  let number3 = number3 
  else {
    fatalError("impossible")
}

samfranz avatar Apr 17 '19 17:04 samfranz

We'd be willing to work on a PR for this but wanted to know if such a contribution would be welcome first.

Yes please! I've come to format guards exactly this way. We also allow one more possiblity:

-----------------------------------------------------| Line length limit
guard let a = ..., let b = ... else { return ... }

sjavora avatar May 15 '20 08:05 sjavora

I wonder if Santa will have this added to SwiftLint for Christmas this year :)

acosmicflamingo avatar Dec 08 '22 00:12 acosmicflamingo