Home AssistantHome AssistantContributors
On this page

The Apple project formats and lints its code automatically, so reviews can focus on behavior and edge cases instead of style.

The tools

Tool Checks Configured in
SwiftFormat Swift formatting .swiftformat
SwiftLint Swift rules SwiftFormat doesn't cover, plus custom rules .swiftlint.yml
RuboCop The Ruby code of Fastlane .rubocop.yml
Yamllint Workflows and other YAML .yamllint.yml

Run them

Shell
# Report problems, change nothing
bundle exec fastlane lint

# Fix what can be fixed automatically
bundle exec fastlane autocorrect

Run autocorrect before every commit. Or let git do it for you:

Shell
bundle exec fastlane install_git_hooks

Inside Xcode, the linters only show warnings and don't change your code. CI also runs Yamllint, which is not part of the lint lane.

What the configuration enforces

  • Formatting: lines up to 120 characters, arguments and collections wrapped before the first element, self only in initializers, guard and else on the same line, and no file header comments.
  • SwiftLint uses an allowlist of rules, not every default rule. Among them: no force_cast or force_try, and low cyclomatic complexity.
  • Custom SwiftLint rules: never assign to Current outside tests, and use SFSafeSymbols instead of raw SF Symbol names.
Swift
// Wrong
Image(systemName: "house")

// Right
Image(systemSymbol: .house)

Suppressing a rule

Be careful with // swiftlint:disable. CI looks for new ones in every pull request, and comments when it finds one (on pull requests from a branch in the repository itself), so a maintainer can check that it is really needed. Every suppression needs a good reason.

Conventions

  • One type per file, named after the type, and a #Preview for every SwiftUI view. See rules for every change.
  • Log with Current.Log, never print or NSLog.
  • Small, well-named types and functions that are easy to test on their own.
  • Shared code goes in shared modules, instead of being copied between targets. Don't put assumptions about one target into shared or extension code.
  • User facing text goes in en.lproj/Localizable.strings. SwiftGen generates the L10n accessors you use in code, and translations come from Lokalise.

Generated files

Some files are generated by tools or workflows, like the L10n accessors and the icon and color sets. Generated files usually say so in a comment at the top. Don't edit them by hand: change the source and run the tool. When you touch Ruby or workflow code, make sure its linters still pass.

Was this page helpful?

Last updated on .

Last verified against the source on .