swiftlang / swift-format

Formatting technology for Swift source code
Apache License 2.0
2.38k stars 216 forks source link

Is `lineBreakBeforeEachArgument = true` broken? #734

Closed alephao closed 1 month ago

alephao commented 1 month ago

Hello, I'm trying to figure if my understanding of what lineBreakBeforeEachArgument = true is supposed to do is wrong or if the current behavior is not correct. Read the Context section below for details.

If the current behavior is the correct one, is having something like lineBreakBeforeEachArgument = always a reasonable feature request?

Context

swift-format version: 510.1.0

My understanding of lineBreakBeforeEachArgument = true is that it will ALWAYS add a line break before function arguments, but in practice it doesn't happen, and after looking at this test case, it seems like my assumption is wrong?

What the documentation says:

lineBreakBeforeEachArgument (boolean): Determines the line-breaking behavior for generic arguments and function arguments when a declaration is wrapped onto multiple lines. If true, a line break will be added before each argument, forcing the entire argument list to be laid out vertically. If false (the default), arguments will be laid out horizontally first, with line breaks only being fired when the line length would be exceeded.

The behavior that I expected:

The negative diff is the original code, and the positive diff is what I expected swift-format to do:

-func oneArg(a: Int) {  }
+func oneArg(
+  a: Int
+) {}

-func twoArgs(a: Int, b: Int) {  }
+func twoArgs(
+  a: Int,
+  b: Int
+) {}

What actually happens:

No changes, the formatting only happens if the lineHeight threshold is met.

How to reproduce locally

You can run the following commands to reproduce, assuming you have swift 510.1.0:

# create the .swift-format config file
cat <<EOF > .swift-format
{
  "indentation" : {
    "spaces" : 2
  },
  "lineBreakBeforeEachArgument" : true,
  "lineLength" : 80,
  "maximumBlankLines" : 1,
  "tabWidth" : 1,
  "version" : 1
}
EOF

# Create the code to be formatted
cat <<EOF > Example.swift
func oneArg(a: Int) {}

func twoArgs(a: Int, b: Int) {}
EOF

# Run swift format
swift-format format Example.swift

Output

func oneArg(a: Int) {}

func twoArgs(a: Int, b: Int) {}
ahoppen commented 1 month ago

Synced to Apple’s issue tracker as rdar://127738473

allevato commented 1 month ago

The behavior you're observing is correct and intentional; line breaks are only inserted if the signature needs to be wrapped. The configuration property's name doesn't spell that out, but that's due to not wanting to make them too verbose.

My personal opinion is that I think it would be hard to rationalize a setting that forces them to wrap when they otherwise don't need to. There's a cost to introducing a large number of configuration options (in terms of complexity, interaction between settings, testing...) and I think we should be opinionated to some degree about what we support.

alephao commented 1 month ago

@allevato thanks for clarifying and sharing your opinion! I'm not super passionate about it, so I'll just close this issue