Swift Formatting Guidelines

(Chéyo Jiménez) #1

There is a mode in SwiftLint where it can automatically apply formatting to files. It would be good if Swift had a formal guideline so we could make this the default (like the go formater )

Github (the company) had a swift style guideline for a long time but decided to stop maintaining it. (I think they moved to TS) There are other guidelines out there but they are mostly for style and none of them official.

I have faith in the community that we can figure out a minimum set of formatting guidelines that can be blessed by the Swift community ala Rust Formatting Guideline

2 Likes
(^) #2

i think everyone has their own set conventions for Swift formatting and you’re unlikely to find a convention everyone or even many people will agree on.

The only “authoritative” source that exists right now is the standard library which has an informal but consistent style, but almost all other (open source) Swift code I’ve seen (including Foundation) does not resemble it in the slightest. (i personally think it’s extremely ugly but that’s irrelevant)

4 Likes
(Chéyo Jiménez) #3

Yeah, no. I do not think the standard library’s style should be what people use. I think we should follow the lead of typescript and separate the standards library style from the recommended style. https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines

1 Like
(^) #4

i went to the link u gave but it told me to stop reading so i came back

2 Likes
(FĂ©lix Fischer) #5

It definitely does. Screaming. XD oh jeez.

Ejem. /ontopic

@masters3d
Do you think there’s something to win from having a formatting guideline? I think that’s what this post is missing. I’d like to know why would we want this and what would this look like in practice at the user level :slight_smile:

(Not trying to sound despective, I actually really wanna know)

1 Like
(^) #6

idk if you were @ing me or him but i personally think there’s nothing to be gained from this conversation other than a protracted fight over brace placement (long live allman style!!!)

I think there’s much more value in producing tooling that can automatically apply user-defined formatting rules. I think i remember @harlanhaskins was working on something like that

1 Like
(FĂ©lix Fischer) #7

I was @ing him, thanks for pointing that out :sweat_smile: now it’s fixed

I agree, and yes, Harlan was working on something like that. Maybe for the GSoC? Lemme fish out the info, I think it was an official swift-format tool

Edit: yep, a swift-format tool in the swift repo.

#8

Yes, I think a tool to apply user-defined formatting rules would be a lot more sensible first step here. Then, if it’s considered worthwhile in future, someone could start the long argument about what the blessed set of rules should be.

2 Likes
(Tony Allevato) #9

I’d like to defend the standard library style (purely as an observer/user, since I’m not on the Swift team and had no hand in creating it) :slight_smile:. It’s definitely something of an odd divergence from usual styles when you first see it (the first time I saw ) { occupying its own line, I was taken aback), but it actually has some quite nice properties that enhance readability and structure.

In fact, at Google we’ve recently based our own style guide on it. As we use it on more and more of our code base there are still some edge cases to shake out, but it’s worked quite well for us so far.

The main property of the stdlib style that I like is that it tends to create logical visual groupings when a declaration needs to be wrapped. Since the stdlib deals heavily with generics, this matters a lot when you have, say, a function that includes a number of generic arguments, regular arguments, and generic constraints:

public func computeSomething<
  Sequence1: Sequence,
  Sequence2: Sequence,
  Result
>(
  _ sequence1: Sequence1,
  _ sequence2: Sequence2
) -> Result
where
  Sequence1.Element == Sequence2.Element,
  Result == Sequence1.Element
{
  // do some things
  // do some more things
}

Some folks are surely bothered by things like the angry-looking >( line, but that can be very easily scanned visually to see what the different parts of the declaration are.

Conversely, the more common line wrapping styles in this case would do things like put the argument after the first parenthesis and then align the others underneath it. That creates “zig-zags” throughout the code because that indentation changes depending on the length of the function name or expression that came before it. You have to scan both vertically and horizontally to find what you’re looking for. In stdlib’s style, you only scan vertically—the arguments are always +2 from where the function started. It’s consistent.

This leads into another big advantage, and a topic of this thread: that style more easily lends itself to being automated, because the set of constraints you need to optimize over shrinks quite a bit. When you discover that a declaration needs to be wrapped, you don’t need to factor in the length of certain things that came before it (like the function name) in your later computations, which then affects whether and how you need to wrap those remaining lines. You just bump yourself in +2 and continue your work. This reduces the number of situations where you have to backtrack and try to find a wrapping that still fits within your column limits.

As an example where this matters, consider that each argument in a Swift function has three parts—label, formal argument, type—where languages like C and Java only have the latter two. In addition to that, Swift’s API naming guidelines encourage that the function name and those labels form a fluent phrase when possible, and that tends to increase the character count of those compared to other C-style languages. The standard library style gives you as much room as possible and handles that situation very elegantly.

And yes, we’ve been lucky to have @harlanhaskins working with us on some tooling related to these problems! We’re looking forward to showing off the progress we’ve made soon and getting the community involved in its further development. :slight_smile:

15 Likes
(Chéyo Jiménez) #10

Nice! I was wondering when google would publish their style guide for swift. Thanks for sharing! Looking forward to contribute. I’ve contributed a couple of rules to SwiftLint and I am a big fan correctable rules aka autocorrect.

Consistency within a team. We already have some of this with API guidelines.. They are guidelines, not compile time errors. If teams do not agree, then create their own rules just like SwiftLint allows.

I think the Google Swift Style Guide is a great start for this effort.

(Tomáš Znamenáček) #11

I would love Swift to have a source code formatter. It’s much easier to say “reformat automatically before committing or submitting a PR” than to discuss code formatting issues in PRs. I have found that I prefer automatic code formatting even in languages where I don’t personally agree with the enforced formatting rules (like in Elm).

That said, SwiftLint’s autocorrect is not just a source code formatter, is it? I would hate the formatter doing semantic changes in the code.

1 Like
(Chéyo Jiménez) #12

Not sure what you mean. The linter has rules which you can turn on so they give you a warning. Some of those rules are correctable, those are the rules that change the code which you can decide to check in.

(Chéyo Jiménez) #13

After reading the style guidelines I have a couple of suggestions:

  1. For top level declarations, prefer private over fileprivate on top level declarations. Swift lint rule I helped write for this use case. I don’t think abolishing fileprivate is a good idea but making meaningful when it occurs is useful.

  2. fileprivate extension and private extension are equivalent because they are top level. Prefer private extension.

  3. public extension, open extension is a bad idea and it makes it too easy to expose members to the public api. I think modifiers on extension should be only valid if they are lowering visibility, so internal extension never makes sense. (I guess that only leaves private extension on my books ha! )

  4. The space required before trailing closures is weird. .map { ... }.filter { ... } this space makes sence for function declarations but not trailing closures. To me a trailing closures is attached to the method in the same way that the . does not have a space .map { ... } .filter { ... }

I think either require a space on both sides of the trailing closure or no space. I personally like no space .map{ ... }.filter{ ... }, makes it easy to identify trailing closures if they are split on multiple lines.

(Tomáš Znamenáček) #14

Those are two different things: formatting source code (making mostly just whitespace changes), and auto-correcting linter rules, which may possibly change the meaning of the program. I am fairly comfortable running automatically the former, but not the latter (SwiftLint does sometimes get things wrong, needing an override). Source code formatter is something I would like to run automatically, with no chance of it breaking anything.

(Adrian Zubarev) #15

Has anyone looked up how AppCode is doing this things? I love how you can setup up various formatting rules (even though not everything is possible). I think it’s a good idea to create standardized code formatter lib that everyone can use (integration for Xcode, for AppCode and other IDE’s or text editors), but I don’t think we can agree on a general Swift code style. I read the google style guide today and I agree with quite a lot of different rules, but at the same time I disagree with others.

I had something similar to SwiftSyntax in mind (a central lib that other toolings can build their support onto with).

(Chéyo Jiménez) #16

Yeah, SwiftLint currently needs to be configured. Do you have examples of when a rule changes semantics which are not equivalent? Would you consider changing top level fileprivate declarations to private declaration a non acceptable semantic change?

(Tony Allevato) #17

If you can find a style guide where nobody in the community can say that, I think you’d win one of computer science’s top awards. :smile:

8 Likes
(Adrian Zubarev) #18

It’s another 1 Million question right? I’m on it (** being sarcastic **).

1 Like
#19

Have you seen https://github.com/nicklockwood/SwiftFormat yet? I use this before every commit. It works very well.

There’s also https://github.com/Jintin/Swimat which integrates into XCode.

1 Like
(Chéyo Jiménez) #20

Yeah. Haven’t used it because of limited configuration via the command line but support is coming.

I’ve heard of people using both SwiftLint and SwiftFormat tool.