SwiftFormat icon indicating copy to clipboard operation
SwiftFormat copied to clipboard

Add multiline function chains rule

Open facumenzella opened this issue 6 years ago • 10 comments

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 avatar Oct 20 '19 18:10 facumenzella

@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.

nicklockwood avatar Oct 20 '19 19:10 nicklockwood

@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 avatar Oct 21 '19 07:10 lordzsolt

@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:

  1. Sometimes it might be preferable to have some chained properties on the first line of the chain
  2. There can easily be a property accessor in the chain, as in the case of skipNil above.

ryanmeisters avatar Oct 21 '19 15:10 ryanmeisters

@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:

  1. Sometimes it might be preferable to have some chained properties on the first line of the chain
  2. There can easily be a property accessor in the chain, as in the case of skipNil above.

Yep, exactly :) I prefer writing it like that as well. So there's quite a bit of nuance required in this rule 😄

lordzsolt avatar Oct 21 '19 18:10 lordzsolt

@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.

facumenzella avatar Oct 26 '19 12:10 facumenzella

Hey @facumenzella, are you planning to update this rule? We would like to utilise it for SwiftUI modifiers

Parabak avatar Jun 12 '23 10:06 Parabak

I have something but it is not ready yet. I haven't have found time to finish it. Hopefully in the following weeks

facumenzella avatar Jun 12 '23 12:06 facumenzella

If you are OK I can join and try to contribute during next weeks as well

Parabak avatar Jun 12 '23 13:06 Parabak

Is anyone still working on this?

Is it possible to support you?

Freelenzer avatar Aug 25 '23 12:08 Freelenzer