Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SwiftUI Property declaration to sub section ordering list #282

Merged
merged 8 commits into from
Aug 1, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 92 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3866,51 +3866,119 @@ _You can enable the following settings in Xcode by running [this script](resourc
* <a id='subsection-organization'></a>(<a href='#subsection-organization'>link</a>) **Within each top-level section, place content in the following order.** This allows a new reader of your code to more easily find what they are looking for. [![SwiftFormat: organizeDeclarations](https://img.shields.io/badge/SwiftFormat-organizeDeclarations-008489.svg)](https://github.com/nicklockwood/SwiftFormat/blob/master/Rules.md#organizeDeclarations)
* Nested types and type aliases
* Static properties
* Class properties
* Static property with body
* Class properties with body
* SwiftUI dynamic properties (@State, @Environment, @Binding, etc)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@miguel-jimenez-0529 what do you think about generalizing this section to be any property with a property wrapper? I'm curious about the reason to scope this specifically to SwiftUI property wrappers. cc: @calda

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Me and Cal had the same conversation. Our conclusion was that there are @ properties like @objc that are not property wrappers. Also a property wrapper doesn't have a common semantic meaning, examples of those are @Referenced, @UniBindable, @Atomic, @Resilient. So grouping all property wrappers when we don't know upfront their functionality was a bit opinionated. Engs may have a better idea on where to place them.
This is different for SwiftUI property wrappers since they all conform to the DynamicProperty protocol and have a common semantic meaning in the sense that they interact with the UI.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sense. Thanks for explaining!

* Instance properties
* Instance properties with body
* Static methods
* Class methods
* Instance methods

* <a id='newline-between-subsections'></a>(<a href='#newline-between-subsections'>link</a>) **Add empty lines between property declarations of different kinds.** (e.g. between static properties and instance properties.) [![SwiftFormat: organizeDeclarations](https://img.shields.io/badge/SwiftFormat-organizeDeclarations-008489.svg)](https://github.com/nicklockwood/SwiftFormat/blob/master/Rules.md#organizeDeclarations)

<details>

Computed properties and properties with property observers should appear at the end of the set of declarations of the same kind. (e.g. instance properties.)

```swift
// WRONG
static let gravityEarth: CGFloat = 9.8
static let gravityMoon: CGFloat = 1.6
var gravity: CGFloat
```swift
// WRONG
class PlanetView: UIView {
static var startOfTime { -CGFloat.greatestFiniteMagnitude / 0 }

// RIGHT
static let gravityEarth: CGFloat = 9.8
static let gravityMoon: CGFloat = 1.6
var atmosphere: Atmosphere {
didSet {
print("oh my god, the atmosphere changed")
}
}

var gravity: CGFloat
```
override class var layerClass: AnyClass {
PlanetLayer.self
}

var gravity: CGFloat

static let speedOfLight: CGFloat = 300_000
}

// RIGHT
class PlanetView: UIView {

static let speedOfLight: CGFloat = 300_000
static var startOfTime { -CGFloat.greatestFiniteMagnitude / 0 }

override class var layerClass: AnyClass {
PlanetLayer.self
}

var gravity: CGFloat
var atmosphere: Atmosphere {
didSet {
print("oh my god, the atmosphere changed")
}
}
}
```

SwiftUI Properties are a special type of property that lives inside SwiftUI views. These views conform to the [`DynamicProperty`](https://developer.apple.com/documentation/swiftui/dynamicproperty) protocol and cause the view's body to re-compute. Given this common functionality and also a similar syntax, it is preferred to group them.

```swift
// WRONG

struct CustomSlider: View {

// MARK: Internal

var body: some View {
...
}

// MARK: Private

@Binding private var value: Value
private let range: ClosedRange<Double>
@Environment(\.sliderStyle) private var style
private let step: Double.Stride
@Environment(\.layoutDirection) private var layoutDirection
}

// RIGHT

struct CustomSlider: View {

// MARK: Internal

var body: some View {
...
}

// MARK: Private

@Environment(\.sliderStyle) private var style
@Environment(\.layoutDirection) private var layoutDirection
@Binding private var value: Value

private let range: ClosedRange<Double>
private let step: Double.Stride
}
```
</details>

* <a id='computed-properties-at-end'></a>(<a href='#computed-properties-at-end'>link</a>) **Computed properties and properties with property observers should appear at the end of the set of declarations of the same kind.** (e.g. instance properties.) [![SwiftFormat: organizeDeclarations](https://img.shields.io/badge/SwiftFormat-organizeDeclarations-008489.svg)](https://github.com/nicklockwood/SwiftFormat/blob/master/Rules.md#organizeDeclarations)

* <a id='newline-between-subsections'></a>(<a href='#newline-between-subsections'>link</a>) **Add empty lines between property declarations of different kinds.** (e.g. between static properties and instance properties.) [![SwiftFormat: organizeDeclarations](https://img.shields.io/badge/SwiftFormat-organizeDeclarations-008489.svg)](https://github.com/nicklockwood/SwiftFormat/blob/master/Rules.md#organizeDeclarations)

<details>

```swift
// WRONG
var atmosphere: Atmosphere {
didSet {
print("oh my god, the atmosphere changed")
}
}
static let gravityEarth: CGFloat = 9.8
static let gravityMoon: CGFloat = 1.6
var gravity: CGFloat

// RIGHT
static let gravityEarth: CGFloat = 9.8
static let gravityMoon: CGFloat = 1.6

var gravity: CGFloat
var atmosphere: Atmosphere {
didSet {
print("oh my god, the atmosphere changed")
}
}
```

</details>
Expand Down
2 changes: 1 addition & 1 deletion Sources/AirbnbSwiftFormatTool/airbnb.swiftformat
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
--enumthreshold 20 # organizeDeclarations
--organizetypes class,struct,enum,extension,actor # organizeDeclarations
--visibilityorder beforeMarks,instanceLifecycle,open,public,package,internal,fileprivate,private # organizeDeclarations
--typeorder nestedType,staticProperty,staticPropertyWithBody,classPropertyWithBody,instanceProperty,instancePropertyWithBody,staticMethod,classMethod,instanceMethod # organizeDeclarations
--typeorder nestedType,staticProperty,staticPropertyWithBody,classPropertyWithBody,swiftUIPropertyWrapper,instanceProperty,instancePropertyWithBody,staticMethod,classMethod,instanceMethod # organizeDeclarations
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

--extensionacl on-declarations # extensionAccessControl
--patternlet inline # hoistPatternLet
--redundanttype inferred # redundantType, propertyType
Expand Down
Loading