Add multiline function chains rule
Hi nicklockwood,
We're currently testing SwiftFormat to see if we can fully replace the current setup we have with Swiftlint right now.
I was looking for a replacement for multiline-function-chains
Chained function calls should be either on the same line or one per line.
I was planning on adding the rule with two options in the following weeks:
- same line
- one per line
I just wanted to make sure it makes sense.
Cheers
@facumenzella sounds like a useful rule, but I would have thought that the most common use would be to prevent a mixture of same-line and multi-line in the same expression, in which case the rule shouldn't require any configuration options at all.
@facumenzella I would be interested in this rule as well. I haven't checked how Swiftlint handles it, but I would like to have some special treatment with Rx.
button
.rx
.tap
.subscribe(onNext: {
// Code here
})
This code just looks shit. Perhaps some rule where short links in the chain do not get moved to the 2nd line? 🤔
@lordzsolt That is interesting. The way I prefer to write rx, for example, is
button.rx.tap
.disposed(by: bag)
.map { /* some optional value */ }
.skipNil // <--- What about non functions/methods?
.do(onNext: { [weak self] in self?.someSideEffect() })
.subscribe(
onError: { /*single line is preferable*/},
onNext: {
/*multiple lines if needed*/
}
)
So two things:
- Sometimes it might be preferable to have some chained properties on the first line of the chain
- There can easily be a property accessor in the chain, as in the case of
skipNilabove.
@lordzsolt That is interesting. The way I prefer to write rx, for example, is
button.rx.tap .disposed(by: bag) .map { /* some optional value */ } .skipNil // <--- What about non functions/methods? .do(onNext: { [weak self] in self?.someSideEffect() }) .subscribe( onError: { /*single line is preferable*/}, onNext: { /*multiple lines if needed*/ } )So two things:
- Sometimes it might be preferable to have some chained properties on the first line of the chain
- There can easily be a property accessor in the chain, as in the case of
skipNilabove.
Yep, exactly :) I prefer writing it like that as well. So there's quite a bit of nuance required in this rule 😄
@nicklockwood agree on not adding those options then.
@ryanmeisters @lordzsolt I've been playing with your example, and I am being able to go from this:
button.rx.tap.disposed(by: bag).map { /* some optional value */ }.skipNil.skipNil2.do(onNext: { [weak self] in self?.someSideEffect() }).subscribe(
onError: { },
onNext: { }
)
to this:
button
.rx
.tap
.disposed(by: bag)
.map { }
.skipNil
.skipNil2
.do(onNext: { [weak self] in self?
.someSideEffect() })
.subscribe(
onError: { },
onNext: { }
))
Inside blocks, the rule is applied as well
I also like to format rx code as you do, but I am not finding a way to achieve it. Would it make sense to play with an option like:
- Allow first N chained and then go multiline
Even if I don't like my current result, I think I can live with it. Anyway, let me know your thoughts.
Hey @facumenzella, are you planning to update this rule? We would like to utilise it for SwiftUI modifiers
I have something but it is not ready yet. I haven't have found time to finish it. Hopefully in the following weeks
If you are OK I can join and try to contribute during next weeks as well
Is anyone still working on this?
Is it possible to support you?