### SwiftVersion Comparison Example Source: https://github.com/airbnb/swift/blob/master/_autodocs/types.md Demonstrates creating SwiftVersion instances and performing comparisons and sorting. ```swift let v1 = SwiftVersion(major: 5, minor: 6) let v2 = SwiftVersion(major: 5, minor: 9) let v3 = SwiftVersion(major: 6, minor: 0) let sorted = [v3, v1, v2].sorted() // [v1, v2, v3] print(v1 < v2) // true print(v1 == v1) // true ``` -------------------------------- ### Start Local Development Server Source: https://github.com/airbnb/swift/blob/master/site/README.md Run this command in your terminal to start the local development server. Open http://localhost:4000 in your browser to preview the site. Updates to the style CSS will be reflected after a reload. If you update the README.md you will need to run `bundle exec rake site:prepare` to see the updates reflected in the site. ```bash bundle exec rake site:serve ``` -------------------------------- ### Get OS and Architecture Information Source: https://github.com/airbnb/swift/blob/master/_autodocs/quick-start.md When reporting issues, provide your operating system and architecture. Use `uname -m` to get the machine hardware name. ```bash uname -m ``` -------------------------------- ### Parse and Run AirbnbSwiftFormatTool Source: https://github.com/airbnb/swift/blob/master/_autodocs/api-reference.md Example of how to parse command-line arguments and execute the AirbnbSwiftFormatTool. Handles potential errors during the formatting process. ```swift do { var tool = AirbnbSwiftFormatTool.parseOrExit() try tool.run() } catch { print("Formatting failed: \(error)") exit(1) } ``` -------------------------------- ### Verify SwiftFormat and SwiftLint Installation Source: https://github.com/airbnb/swift/blob/master/_autodocs/quick-start.md Check if SwiftFormat and SwiftLint binaries are installed and accessible in your PATH. If missing, reset and reinstall the plugin. ```bash # Verify binaries are installed which swiftformat which swiftlint # If missing, reinstall plugin swift package reset swift package format ``` -------------------------------- ### Package Swift Version Detection Example Source: https://github.com/airbnb/swift/blob/master/_autodocs/types.md Demonstrates accessing the minimum Swift version supported by a package using the extended Package type. ```swift let package = context.package let minVersion = package.minimumSwiftVersion let versionString = "\(minVersion.major).\(minVersion.minor)" ``` -------------------------------- ### Process Shell Command Usage Example Source: https://github.com/airbnb/swift/blob/master/_autodocs/types.md Shows how to use the shellCommand computed property after setting launch path and arguments on a Process instance. ```swift let process = Process() process.launchPath = "/usr/bin/swiftformat" process.arguments = ["/path/to/sources", "--lint"] print(process.shellCommand) // "/usr/bin/swiftformat /path/to/sources --lint" ``` -------------------------------- ### Command Invocation for Formatting Source: https://github.com/airbnb/swift/blob/master/_autodocs/api-reference.md Example of running a command-line tool with logging enabled. Checks the exit code to determine success or failure. ```swift let cmd = Command( log: true, launchPath: "/usr/bin/swiftformat", arguments: ["/path/to/sources"] ) let exitCode = try cmd.run() if exitCode == 0 { print("Success") } else { print("Failed with code \(exitCode)") } ``` -------------------------------- ### Specify Swift version for formatting Source: https://github.com/airbnb/swift/blob/master/_autodocs/overview.md Set the Swift language version for the formatting process. '5.9' is an example; use your project's required version. ```bash swift package format --swift-version 5.9 ``` -------------------------------- ### Swift Rule Example Source: https://github.com/airbnb/swift/blob/master/CONTRIBUTING.md Illustrates the incorrect and correct code patterns for a new Swift style rule. Use this format to demonstrate the rule's purpose. ```swift // WRONG func someIncorrectCode {} // GOOD func someGoodCode {} ``` -------------------------------- ### Swift Version Detection for Tool Configuration Source: https://github.com/airbnb/swift/blob/master/_autodocs/api-reference.md Example of detecting the minimum Swift version from a package and using it to configure the AirbnbSwiftFormatTool. This ensures compatibility with the project's Swift version. ```swift let package = ... // PluginContext.package let minVersion = package.minimumSwiftVersion let versionString = "\(minVersion.major).\(minVersion.minor)" let tool = AirbnbSwiftFormatTool( directories: [...], swiftFormatPath: ..., swiftLintPath: ..., swiftVersion: versionString ) ``` -------------------------------- ### Get Swift Version Source: https://github.com/airbnb/swift/blob/master/_autodocs/quick-start.md To report issues, include the version of Swift you are using. Run `swift --version` to retrieve this information. ```bash swift --version ``` -------------------------------- ### Direct AirbnbSwiftFormatTool Invocation Source: https://github.com/airbnb/swift/blob/master/_autodocs/api-reference.md Example of using the AirbnbSwiftFormatTool directly to format code. Set `lint: false` to enable autocorrection. ```swift // Using the executable tool directly let tool = AirbnbSwiftFormatTool( directories: ["/path/to/Sources"], swiftFormatPath: "/usr/bin/swiftformat", swiftLintPath: "/usr/bin/swiftlint", lint: false // Autocorrect enabled ) do { try tool.run() print("Formatting succeeded") } catch { print("Formatting failed with error: \(error)") exit(1) } ``` -------------------------------- ### Format Code and Commit Changes Source: https://github.com/airbnb/swift/blob/master/_autodocs/quick-start.md Format your code locally to match the style guide and then commit the changes. This is a common fix for lint failures in CI environments. ```bash swift package format git add . git commit -m "Auto-format to match style guide" git push ``` -------------------------------- ### CommandError Usage Example Source: https://github.com/airbnb/swift/blob/master/_autodocs/types.md Demonstrates how to catch and handle CommandError exceptions, specifically differentiating between lint failures and other unknown errors with their exit codes. ```swift do { try plugin.performCommand(context: context, arguments: arguments) } catch CommandError.lintFailure { print("Formatting or linting failed") } catch CommandError.unknownError(let code) { print("Unexpected exit code: \(code)") } ``` -------------------------------- ### SPM Plugin Usage for Formatting Source: https://github.com/airbnb/swift/blob/master/_autodocs/api-reference.md Example of using the Swift Package Manager plugin to format code. This command-line interface allows specifying paths, exclusions, Swift versions, and linting options. ```bash swift package format \ --paths Sources Tests \ --exclude Resources \ --swift-version 5.9 \ --lint ``` -------------------------------- ### Swift Conditional Assignment Examples Source: https://github.com/airbnb/swift/blob/master/README.md Illustrates correct and incorrect ways to assign values using if and switch statements. Highlights the advantages of expression-based assignment for conciseness and type inference. ```swift // WRONG let planetLocation: String if let star = planet.star { planetLocation = "The \(star.name) system" } else { planetLocation = "Rogue planet" } let planetType: PlanetType switch planet { case .mercury, .venus, .earth, .mars: planetType = .terrestrial case .jupiter, .saturn, .uranus, .neptune: planetType = .gasGiant } let canBeTerraformed: Bool if let star = planet.star, !planet.isHabitable, planet.isInHabitableZone(of: star) { canBeTerraformed = true } else { canBeTerraformed = false } ``` ```swift // RIGHT let planetLocation = if let star = planet.star { "The \(star.name) system" } else { "Rogue planet" } let planetType: PlanetType = switch planet { case .mercury, .venus, .earth, .mars: .terrestrial case .jupiter, .saturn, .uranus, .neptune: .gasGiant } let canBeTerraformed = if let star = planet.star, !planet.isHabitable, planet.isInHabitableZone(of: star) { true } else { false } ``` ```swift // ALSO RIGHT. This example cannot be converted to an if/switch expression // because one of the branches is more than just a single expression. let planetLocation: String if let star = planet.star { planetLocation = "The \(star.name) system" } else { let actualLocaton = galaxy.name ?? "the universe" planetLocation = "Rogue planet somewhere in \(actualLocaton)" } ``` -------------------------------- ### Swift Acronym Naming Conventions Source: https://github.com/airbnb/swift/blob/master/README.md Acronyms in names should be all-caps, except when at the start of a lowerCamelCase name, where they should be uniformly lower-cased. This example shows the incorrect and correct ways to name classes, methods, and variables involving acronyms like URL and ID. ```swift // WRONG class UrlValidator { func isValidUrl(_ URL: URL) -> Bool { ... } func isProfileUrl(_ URL: URL, for userId: String) -> Bool { ... } } let URLValidator = UrlValidator() let isProfile = URLValidator.isProfileUrl(URLToTest, userId: IDOfUser) // RIGHT class URLValidator { func isValidURL(_ url: URL) -> Bool { ... } func isProfileURL(_ url: URL, for userID: String) -> Bool { ... } } let urlValidator = URLValidator() let isProfile = urlValidator.isProfileURL(urlToTest, userID: idOfUser) ``` -------------------------------- ### Omit `get` from Simple Computed Properties Source: https://github.com/airbnb/swift/blob/master/README.md When a computed property only has a `get` clause and no `set`, `willSet`, or `didSet`, omit the `get` keyword for conciseness. ```swift // WRONG var universe: Universe { get { Universe() } } // RIGHT var universe: Universe { Universe() } // RIGHT var universe: Universe { get { multiverseService.current } set { multiverseService.current = newValue } } ``` -------------------------------- ### View Bundled Configuration Source: https://github.com/airbnb/swift/blob/master/_autodocs/quick-start.md Inspect enabled SwiftFormat rules by parsing the output of `swift package describe` or by directly reading the configuration files from the package source. ```bash # SwiftFormat rules strings $(swift package describe 2>/dev/null | grep -o '/.*swift') | grep -E '^--' ``` ```bash # Or read the package source cat Sources/AirbnbSwiftFormatTool/airbnb.swiftformat ``` ```bash cat Sources/AirbnbSwiftFormatTool/swiftlint.yml ``` -------------------------------- ### AirbnbSwiftFormatPlugin.performCommand(context:inputPaths:arguments:) Source: https://github.com/airbnb/swift/blob/master/_autodocs/module-graph.md Performs the formatting command with specified context, input paths, and arguments. ```APIDOC ## performCommand(context:inputPaths:arguments:) ### Description Performs the formatting command with specified context, input paths, and arguments. ### Method public ### Parameters - **context** (CommandContext) - Required - **inputPaths** ([String]) - Required - **arguments** ([String]) - Required ### Returns Void ### Throws CommandError ``` -------------------------------- ### Perform Command (Main Implementation) Source: https://github.com/airbnb/swift/blob/master/_autodocs/api-reference.md This is the core implementation for formatting Swift files. It handles path filtering, binary locating, cache path construction, tool spawning, and error handling for lint failures. Use this when directly invoking the formatting logic. ```swift try plugin.performCommand( context: pluginContext, inputPaths: ["/path/to/Sources"], arguments: ["--lint", "--log"] ) ``` -------------------------------- ### Get Tool Path using CommandContext Source: https://github.com/airbnb/swift/blob/master/_autodocs/api-reference.md Resolves the absolute path to a bundled tool by name. Use this to get the path to executables like swiftformat or swiftlint. ```swift let swiftFormatPath = try context.tool(named: "swiftformat").path.string ``` -------------------------------- ### AirbnbSwiftFormatPlugin.performCommand(context:arguments:) Source: https://github.com/airbnb/swift/blob/master/_autodocs/module-graph.md Performs the formatting command asynchronously with specified context and arguments. ```APIDOC ## performCommand(context:arguments:) ### Description Performs the formatting command asynchronously with specified context and arguments. ### Method public async ### Parameters - **context** (PluginContext) - Required - **arguments** ([String]) - Required ### Returns Void ### Throws CommandError ``` -------------------------------- ### Instantiate and Run a Shell Command Source: https://github.com/airbnb/swift/blob/master/_autodocs/api-reference.md Instantiate a `Command` with logging enabled, executable path, and arguments. Then, execute the command using its `run()` method and print the exit code. This is useful for invoking external tools like swiftformat. ```swift let cmd = Command( log: true, launchPath: "/usr/bin/swiftformat", arguments: ["/path/to/sources", "--lint"] ) let exitCode = try cmd.run() print("Exit code: \(exitCode)") ``` -------------------------------- ### Fix #file Usage Violation Source: https://github.com/airbnb/swift/blob/master/_autodocs/quick-start.md Replace the usage of `#file` with `#fileID` to get a more specific identifier, which is often preferred. ```swift let file = #file ``` ```swift let file = #fileID ``` -------------------------------- ### Specify Paths and Targets for Formatting Source: https://github.com/airbnb/swift/blob/master/site/src/plugin.md Explicitly list the paths or Swift Package Manager targets that the format command should process. ```shell $ swift package format --paths Sources Tests Package.swift ``` ```shell $ swift package format --targets AirbnbSwiftFormatTool ``` -------------------------------- ### AirbnbSwiftFormatPlugin.performCommand(context:arguments:) Source: https://github.com/airbnb/swift/blob/master/_autodocs/module-graph.md Performs the formatting command with specified Xcode context and arguments. ```APIDOC ## performCommand(context:arguments:) ### Description Performs the formatting command with specified Xcode context and arguments. ### Method public ### Parameters - **context** (XcodePluginContext) - Required - **arguments** ([String]) - Required ### Returns Void ### Throws CommandError ``` -------------------------------- ### Run Swift Package Format Command Source: https://github.com/airbnb/swift/blob/master/site/src/plugin.md Execute the 'format' command plugin in your package directory to automatically reformat your code. ```shell $ swift package format ``` -------------------------------- ### Format entire package with interactive prompt Source: https://github.com/airbnb/swift/blob/master/_autodocs/overview.md Use this command to format your entire Swift package. It will prompt for interactive permission before writing changes. ```bash swift package format ``` -------------------------------- ### Format Process as Shell Command Source: https://github.com/airbnb/swift/blob/master/_autodocs/api-reference.md Formats the process's launch path and arguments as a shell command string for logging. Use this to log the exact command being executed. ```swift let process = Process() process.launchPath = "/usr/bin/swiftformat" process.arguments = ["/path/to/source", "--lint"] print(process.shellCommand) // "/usr/bin/swiftformat /path/to/source --lint" ``` -------------------------------- ### Get Minimum Swift Version for Package Source: https://github.com/airbnb/swift/blob/master/_autodocs/api-reference.md Access the minimum Swift version supported by the package. This computed property aggregates versions from Package.swift and version-specific manifests. ```swift let minVersion = package.minimumSwiftVersion print("\(minVersion.major).\(minVersion.minor)") // e.g., "5.6" ``` -------------------------------- ### performCommand (Main Implementation) Source: https://github.com/airbnb/swift/blob/master/_autodocs/api-reference.md The main implementation of the command plugin, handling path filtering, binary location, and tool execution. ```APIDOC ## performCommand (Main Implementation) ### Description Shared implementation that filters input paths, locates SwiftFormat and related binaries, constructs cache paths, and spawns the AirbnbSwiftFormatTool. It throws `CommandError.lintFailure` if the tool exits with failure. ### Signature ```swift func performCommand( context: CommandContext, inputPaths: [String], arguments: [String] ) throws ``` ### Parameters #### Path Parameters - `context` (CommandContext) - Required - Provides access to tools and work directory - `inputPaths` ([String]) - Required - Paths to Swift files/directories to format - `arguments` ([String]) - Required - Additional user-provided arguments (e.g., `--lint`, `--log`) ### Returns `Void` ### Throws `CommandError` on execution failure ### Request Example ```swift try plugin.performCommand( context: pluginContext, inputPaths: ["/path/to/Sources"], arguments: ["--lint", "--log"] ) ``` ``` -------------------------------- ### SwiftFormat: Blank Lines in Scope Source: https://github.com/airbnb/swift/blob/master/README.md Ensures consistent use of blank lines at the start and end of scopes to improve code readability. Demonstrates correct and incorrect placement. ```swift // WRONG class Planet { func terraform() { generateAtmosphere() generateOceans() } } // RIGHT class Planet { func terraform() { generateAtmosphere() generateOceans() } } // ALSO RIGHT class Planet { func terraform() { generateAtmosphere() generateOceans() } } // WRONG: Not consistent class Planet { func terraform() { generateAtmosphere() generateOceans() } } // WRONG: Not consistent class Planet { func terraform() { generateAtmosphere() generateOceans() } } ``` -------------------------------- ### Prefer Guard Over If for Precondition Validation in Swift Source: https://github.com/airbnb/swift/blob/master/README.md Use `guard` statements for validating preconditions at the start of a scope to reduce nesting and ensure compiler verification of return statements. ```swift // WRONG func land(on planet: Planet) { if !planet.hasAtmosphere { abortLanding() return } engine.decelerate() } ``` ```swift // WRONG: Oops! forgot "return" in precondition. func land(on planet: Planet) { if !planet.hasAtmosphere { abortLanding() } engine.decelerate() } ``` ```swift // RIGHT func land(on planet: Planet) { guard planet.hasAtmosphere else { abortLanding() return } engine.decelerate() } ``` -------------------------------- ### Multiline String Literal Indentation in Swift Source: https://github.com/airbnb/swift/blob/master/README.md Applies consistent indentation to multiline string literals. The body and closing triple-quote should be indented, unless the literal starts on its own line. ```swift // WRONG var spaceQuote = """ “Space,” it says, “is big. Really big. You just won’t believe how vastly, hugely, mindbogglingly big it is. I mean, you may think it’s a long way down the road to the chemist’s, but that’s just peanuts to space.” " // RIGHT var spaceQuote = """ “Space,” it says, “is big. Really big. You just won’t believe how vastly, hugely, mindbogglingly big it is. I mean, you may think it’s a long way down the road to the chemist’s, but that’s just peanuts to space.” " // WRONG var universeQuote: String { """ In the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move. """ } // RIGHT var universeQuote: String { """ In the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move. """ } ``` -------------------------------- ### Use @Entry for Environment Keys in Swift Source: https://github.com/airbnb/swift/blob/master/README.md Demonstrates the modern approach to environment keys using the @Entry macro, replacing the legacy manual implementation. ```swift /// WRONG: The `EnvironmentValues` property depends on `IsSelectedEnvironmentKey` struct IsSelectedEnvironmentKey: EnvironmentKey { static var defaultValue: Bool { false } } extension EnvironmentValues { var isSelected: Bool { get { self[IsSelectedEnvironmentKey.self] } set { self[IsSelectedEnvironmentKey.self] = newValue } } } /// RIGHT: The `EnvironmentValues` property uses the @Entry macro extension EnvironmentValues { @Entry var isSelected: Bool = false } ``` -------------------------------- ### Catch Specific Plugin Errors in Swift Source: https://github.com/airbnb/swift/blob/master/_autodocs/errors.md Handle potential errors during plugin command execution. This example demonstrates catching `CommandError.lintFailure` and `CommandError.unknownError`, as well as any other unexpected errors. ```swift do { try plugin.performCommand(context: context, arguments: arguments) } catch CommandError.lintFailure { print("Lint violations detected") exit(1) } catch CommandError.unknownError(let exitCode) { print("Unknown error: exit code \(exitCode)") exit(exitCode) } catch { print("Unexpected error: \(error)") exit(1) } ``` -------------------------------- ### Swift Package Manager Dependency Chain Source: https://github.com/airbnb/swift/blob/master/_autodocs/module-graph.md Illustrates how a user's package integrates with the Airbnb Swift plugin. Consumers only interact with the plugin via `swift package format`, which abstracts away the SwiftFormat and SwiftLint binaries, configuration files, and argument marshaling. ```text User's Package.swift └─ Dependency: "https://github.com/airbnb/swift" └─ Provides: FormatSwift plugin └─ Invocable: swift package format ``` -------------------------------- ### Project File Organization Source: https://github.com/airbnb/swift/blob/master/_autodocs/README.md Illustrates the directory structure for the Swift project, showing the location and purpose of each markdown file. ```text output/ ├── README.md (this file – document index and overview) ├── overview.md (project architecture and purpose) ├── api-reference.md (exported functions, classes, methods) ├── configuration.md (all configuration options) ├── types.md (type definitions and protocols) ├── errors.md (error codes and violation catalog) ├── module-graph.md (module structure and dependencies) └── quick-start.md (usage examples and troubleshooting) ``` -------------------------------- ### Check SwiftFormat and SwiftLint Versions Source: https://github.com/airbnb/swift/blob/master/_autodocs/errors.md Verify the versions of SwiftFormat and SwiftLint by running their respective version commands. Ensure these versions match the bundled versions specified in your `Package.swift` file to avoid compatibility issues. ```bash swiftformat --version swiftlint version ``` -------------------------------- ### Suppressing SwiftLint Rules Source: https://github.com/airbnb/swift/blob/master/_autodocs/quick-start.md When a SwiftLint rule needs to be temporarily disabled, use a comment to explain the reason. This example shows how to suppress the `no_direct_standard_out_logs` rule for specific debug logging. ```swift // swiftlint:disable:next no_direct_standard_out_logs // Debug logging only; this line is stripped in release builds print("Memory usage: \(memoryFootprint)") ``` -------------------------------- ### Swift Objective-C-Style Acronym Prefixes Source: https://github.com/airbnb/swift/blob/master/README.md Avoid Objective-C-style acronym prefixes in Swift class names, as they are unnecessary for avoiding naming conflicts. This example shows the incorrect and correct way to name a class. ```swift // WRONG class AIRAccount { ... } // RIGHT class Account { ... } ``` -------------------------------- ### AirbnbSwiftFormatTool Executable Arguments Source: https://github.com/airbnb/swift/blob/master/_autodocs/configuration.md Use these arguments when invoking the AirbnbSwiftFormatTool directly. Specify directories to format, paths to SwiftFormat and SwiftLint executables, and optional configuration or cache paths. ```bash AirbnbSwiftFormatTool \ --swift-format-path \ --swift-lint-path \ [--swift-format-config ] \ [--swift-lint-config ] \ [--swift-format-cache-path ] \ [--swift-lint-cache-path ] \ [--swift-version ] \ [--lint] \ [--log] ``` -------------------------------- ### Swift Type and Property Naming Source: https://github.com/airbnb/swift/blob/master/README.md Use UpperCamelCase for type and protocol names, and lowerCamelCase for properties, methods, and variables. This example demonstrates correct naming for a protocol, class, enum, and instance variables. ```swift protocol SpaceThing { ... } class SpaceFleet: SpaceThing { enum Formation { ... } class Spaceship { ... } var ships: [Spaceship] = [] static let worldName: String = "Earth" func addShip(_ ship: Spaceship) { ... } } let myFleet = SpaceFleet() ``` -------------------------------- ### Mock Command.runCommand for Testing Source: https://github.com/airbnb/swift/blob/master/_autodocs/types.md This snippet demonstrates how to mock the `Command.runCommand` closure for testing purposes. It temporarily replaces the default implementation with a custom mock and restores the original afterward using `defer`. ```swift // Mock Command.runCommand for testing let originalRunCommand = Command.runCommand Command.runCommand = { command in // Custom mock logic return 0 } defer { Command.runCommand = originalRunCommand } ``` -------------------------------- ### AirbnbSwiftFormatTool Executable Source: https://github.com/airbnb/swift/blob/master/_autodocs/overview.md The `AirbnbSwiftFormatTool` executable can be used directly and accepts various command-line arguments for fine-grained control. ```APIDOC ## AirbnbSwiftFormatTool ### Description An executable tool for formatting and linting Swift code with customizable paths for binaries and configuration files. ### Usage ```bash AirbnbSwiftFormatTool --swift-format-path --swift-lint-path [options] ``` ### Arguments - `directories` (positional): Swift source directories to format. ### Options - `--swift-format-path` (required): Path to the SwiftFormat binary. - `--swift-lint-path` (required): Path to the SwiftLint binary. - `--swift-format-config`: Path to SwiftFormat config (defaults to bundled `airbnb.swiftformat`). - `--swift-lint-config`: Path to SwiftLint config (defaults to bundled `swiftlint.yml`). - `--swift-format-cache-path`: Optional cache directory for SwiftFormat. - `--swift-lint-cache-path`: Optional cache directory for SwiftLint. - `--swift-version`: Project's minimum Swift version (defaults to Package.swift version). - `--lint`: Enable lint-only mode (no autocorrect). - `--log`: Enable verbose logging of executed commands. ``` -------------------------------- ### Use Underscores for Unused Swift Parameters Source: https://github.com/airbnb/swift/blob/master/README.md Naming unused parameters with an underscore clarifies their non-usage, aiding in the detection of logical errors and simplifying method signatures. This applies to both WRONG and RIGHT examples demonstrating the impact. ```swift // WRONG // In this method, the `newCondition` parameter is unused. // This is actually a logical error, and is easy to miss, but compiles without warning. func updateWeather(_ newCondition: WeatherCondition) -> Weather { var updatedWeather = self updatedWeather.condition = condition // this mistake inadvertently makes this method unable to change the weather condition return updatedWeather } // In this method, the `color` parameter is unused. // Is this a logical error (e.g. should it be passed through to the `universe.generateStars` method call), // or is this an unused argument that should be removed from the method signature? func generateUniverseWithStars( at location: Point, count: Int, color: StarColor, withAverageDistance averageDistance: Float ) { let universe = generateUniverse() universe.generateStars( at: location, count: count, withAverageDistance: averageDistance ) } ``` ```swift // RIGHT // Automatically reformatting the unused parameter to be an underscore // makes it more clear that the parameter is unused, which makes it // easier to spot the logical error. func updateWeather(_: WeatherCondition) -> Weather { var updatedWeather = self updatedWeather.condition = condition return updatedWeather } // The underscore makes it more clear that the `color` parameter is unused. // This method argument can either be removed if truly unnecessary, // or passed through to `universe.generateStars` to correct the logical error. func generateUniverseWithStars( at location: Point, count: Int, color _: StarColor, withAverageDistance averageDistance: Float ) { let universe = generateUniverse() universe.generateStars( at: location, count: count, withAverageDistance: averageDistance ) } ``` -------------------------------- ### AirbnbSwiftFormatTool Executable Arguments Source: https://github.com/airbnb/swift/blob/master/_autodocs/overview.md Arguments for the AirbnbSwiftFormatTool executable. Specify SwiftFormat and SwiftLint paths, configuration files, cache directories, Swift version, and lint-only mode. ```bash directories (positional): Swift source directories to format --swift-format-path (required): Path to SwiftFormat binary --swift-lint-path (required): Path to SwiftLint binary --swift-format-config: Path to SwiftFormat config (defaults to bundled `airbnb.swiftformat`) --swift-lint-config: Path to SwiftLint config (defaults to bundled `swiftlint.yml`) --swift-format-cache-path: Optional cache directory for SwiftFormat --swift-lint-cache-path: Optional cache directory for SwiftLint --swift-version: Project's minimum Swift version (defaults to Package.swift version) --lint: Enable lint-only mode (no autocorrect) --log: Enable verbose logging of executed commands ``` -------------------------------- ### Swift Event-Handling Function Naming Source: https://github.com/airbnb/swift/blob/master/README.md Name event-handling functions using past-tense sentences, like `didTapButton` instead of `handleTap`. The subject can be omitted if not needed for clarity. This example contrasts incorrect and correct naming for event handlers. ```swift // WRONG class ExperiencesViewController { private func handleBookButtonTap() { ... } private func modelChanged() { ... } } // RIGHT class ExperiencesViewController { private func didTapBookButton() { ... } private func modelDidChange() { ... } } ``` -------------------------------- ### Specify Paths for Swift Package Format Source: https://github.com/airbnb/swift/blob/master/README.md Explicitly list the paths and/or Swift Package Manager targets to format using the '--paths' or '--targets' flags. ```shell $ swift package format --paths Sources Tests Package.swift ``` ```shell $ swift package format --targets AirbnbSwiftFormatTool ``` -------------------------------- ### Remove Blank Lines Between Chained Swift Functions Source: https://github.com/airbnb/swift/blob/master/README.md Eliminating blank lines between chained function calls enhances code readability by clearly showing the sequence of operations. Examples demonstrate WRONG and RIGHT formatting for chained methods. ```swift // WRONG var innerPlanetNames: [String] { planets .filter { $0.isInnerPlanet } .map { $0.name } } // WRONG var innerPlanetNames: [String] { planets .filter { $0.isInnerPlanet } // Gets the name of the inner planet .map { $0.name } } ``` ```swift // RIGHT var innerPlanetNames: [String] { planets .filter { $0.isInnerPlanet } .map { $0.name } } // RIGHT var innerPlanetNames: [String] { planets .filter { $0.isInnerPlanet } // Gets the name of the inner planet .map { $0.name } } ``` -------------------------------- ### URL Macro for Static URLs Source: https://github.com/airbnb/swift/blob/master/README.md Demonstrates using the `#URL(_:)` macro for creating `URL` instances from static strings. This provides compile-time validation and avoids runtime crashes. ```swift // WRONG let url = URL(string: "https://example.com")! // RIGHT let url = #URL("https://example.com") ``` -------------------------------- ### Module Dependency Graph Source: https://github.com/airbnb/swift/blob/master/_autodocs/module-graph.md Illustrates the flow of execution and dependencies when the 'swift package format' command is invoked, from user input to the final exit code. ```text User invokes: swift package format ↓ FormatSwift Plugin (CommandPlugin/XcodeCommandPlugin) ├─ Reads: PluginContext or XcodePluginContext ├─ Resolves: Swift version via Package.minimumSwiftVersion ├─ Determines: Input paths (targets/directories) └─ Uses: CommandContext protocol ↓ AirbnbSwiftFormatPlugin.performCommand(context:inputPaths:arguments:) ├─ Uses: context.tool(named:) from CommandContext ├─ Locates: SwiftFormat binary ├─ Locates: SwiftLint binary ├─ Locates: AirbnbSwiftFormatTool binary └─ Constructs: Arguments ↓ Spawns: AirbnbSwiftFormatTool (executable) ├─ Creates: Command (SwiftFormat) ├─ Runs: Command via Process ├─ Polls: Exit code ├─ Creates: Command (SwiftLint autocorrect, if not lint-only) ├─ Runs: Command via Process ├─ Creates: Command (SwiftLint lint) └─ Aggregates: Exit codes ↓ Returns: Exit code (0 = success, >0 = failure) ├─ CommandError.lintFailure if violations exist └─ CommandError.unknownError(exitCode:) if unexpected code ``` -------------------------------- ### Format Code in CI/CD Pipeline Source: https://github.com/airbnb/swift/blob/master/_autodocs/quick-start.md Integrate swift package format into your CI/CD workflow to automatically check for formatting violations. This example uses GitHub Actions. The command will exit with a non-zero code if violations exist, failing the CI job. ```yaml # .github/workflows/lint.yml name: Lint on: [pull_request] jobs: lint: runs-on: macos-13 steps: - uses: actions/checkout@v3 - uses: swift-actions/setup-swift@v1 - run: swift package format --lint --allow-writing-to-package-directory ``` -------------------------------- ### Lint Swift Package for CI/CD Source: https://github.com/airbnb/swift/blob/master/_autodocs/README.md Integrate this command into your CI/CD pipeline to lint Swift code. It will fail the build if formatting violations are found. Ensure users run `swift package format` locally before pushing. ```bash swift package format --lint --allow-writing-to-package-directory ``` -------------------------------- ### Else Statements on Same Line as Closing Brace Source: https://github.com/airbnb/swift/blob/master/README.md Ensures 'else' statements start on the same line as the previous condition's closing brace. This rule applies unless conditions are separated by a blank line or comments, promoting consistent control flow formatting. ```swift // WRONG if let galaxy { ... } else if let bigBangService { ... } else { ... } // RIGHT if let galaxy { ... } else if let bigBangService { ... } else { ... } // RIGHT, because there are comments between the conditions if let galaxy { ... } // If the galaxy hasn't been created yet, create it using the big bang service else if let bigBangService { ... } // If the big bang service doesn't exist, fail gracefully else { ... } // RIGHT, because there are blank lines between the conditions if let galaxy { ... } else if let bigBangService { // If the galaxy hasn't been created yet, create it using the big bang service ... } else { // If the big bang service doesn't exist, fail gracefully ... } ``` -------------------------------- ### Direct Tool Invocation Source: https://github.com/airbnb/swift/blob/master/_autodocs/quick-start.md Invoke the `AirbnbSwiftFormatTool` directly for custom CI/CD pipelines, embedded build systems, or monorepo scenarios. Specify paths and tool locations, and enable linting with the `--lint` flag. ```bash AirbnbSwiftFormatTool \ /path/to/sources \ --swift-format-path /opt/bin/swiftformat \ --swift-lint-path /opt/bin/swiftlint \ --lint ``` -------------------------------- ### SwiftFormat: Organize Declarations within Types Source: https://github.com/airbnb/swift/blob/master/README.md Demonstrates the recommended order for organizing declarations within Swift types and extensions, including nested types, properties, and methods. ```swift // MARK: Lifecycle // MARK: Open // MARK: Public // MARK: Package // MARK: Internal // MARK: Fileprivate // MARK: Private ``` -------------------------------- ### Package.minimumSwiftVersion Extension Source: https://github.com/airbnb/swift/blob/master/_autodocs/types.md Extends PackagePlugin's `Package` type to provide Swift version detection. ```APIDOC ## Package.minimumSwiftVersion Extension ### Description Extends PackagePlugin's `Package` type to provide Swift version detection. ### Properties - **minimumSwiftVersion** (SwiftVersion) - Computed; lowest supported Swift version - **supportedSwiftVersions** (private) ([SwiftVersion]) - All Swift versions supported by this package ### Methods - **parseSwiftVersion(from:)** (private) ((Substring) -> SwiftVersion?) - Parses "5.9" string to SwiftVersion ### Version Detection Logic 1. Reads `swift-tools-version` from Package.swift 2. Scans for version-specific manifests (Package@swift-X.Y.swift) 3. Parses version from comment: `// swift-tools-version: 5.9` 4. Returns minimum of all supported versions ### Example ```swift let package = context.package let minVersion = package.minimumSwiftVersion let versionString = "\(minVersion.major).\(minVersion.minor)" ``` ``` -------------------------------- ### Architecture Diagram Source: https://github.com/airbnb/swift/blob/master/_autodocs/overview.md Illustrates the architectural flow of the FormatSwift plugin, from the CommandPlugin/XcodeCommandPlugin entry point down to its dependencies like SwiftFormat and SwiftLint. ```text FormatSwift Plugin (CommandPlugin/XcodeCommandPlugin) ↓ AirbnbSwiftFormatPlugin (plugin coordinator) ↓ AirbnbSwiftFormatTool (executable) ├─ SwiftFormat (binary dependency) ├─ SwiftLint (binary dependency) └─ ArgumentParser (swift-argument-parser 1.0.3+) ``` -------------------------------- ### Wrap Function Declaration Arguments in Swift Source: https://github.com/airbnb/swift/blob/master/README.md Demonstrates the correct way to format multi-line function declarations in Swift. Ensure arguments and return types are clearly separated for readability. ```swift class Universe { // WRONG func generateStars(at location: Point, count: Int, color: StarColor, withAverageDistance averageDistance: Float) -> String { // This is too long and will probably auto-wrap in a weird way } // WRONG func generateStars(at location: Point, count: Int, color: StarColor, withAverageDistance averageDistance: Float) { // Xcode indents all the arguments } // WRONG func generateStars( at location: Point, count: Int, color: StarColor, withAverageDistance averageDistance: Float) -> String { populateUniverse() // this line blends in with the argument list } // WRONG func generateStars( at location: Point, count: Int, color: StarColor, withAverageDistance averageDistance: Float) throws -> String { populateUniverse() // this line blends in with the argument list } // WRONG func generateStars( at location: Point, count: Int, color: StarColor, withAverageDistance averageDistance: Float) async throws // these effects are easy to miss since they're visually associated with the last parameter -> String { populateUniverse() } // RIGHT func generateStars( at location: Point, count: Int, color: StarColor, withAverageDistance averageDistance: Float ) -> String { populateUniverse() } // RIGHT func generateStars( at location: Point, count: Int, color: StarColor, withAverageDistance averageDistance: Float ) async throws -> String { populateUniverse() } } ``` -------------------------------- ### Invoke SwiftFormat with Custom Configuration Source: https://github.com/airbnb/swift/blob/master/_autodocs/quick-start.md Pass the path to your custom SwiftFormat configuration file when invoking the tool directly. Ensure SwiftFormat and SwiftLint binaries are correctly specified. ```bash AirbnbSwiftFormatTool Sources \ --swift-format-path /usr/bin/swiftformat \ --swift-lint-path /usr/bin/swiftlint \ --swift-format-config ./.swiftformat ``` -------------------------------- ### Specify Swift Version for Formatting Source: https://github.com/airbnb/swift/blob/master/_autodocs/quick-start.md Format your code assuming a specific Swift syntax version. By default, the tool auto-detects the version from Package.swift. ```bash # Format assuming Swift 5.9 syntax swift package format --swift-version 5.9 # Auto-detect from Package.swift (default) swift package format ``` -------------------------------- ### SwiftFormat: MARK Comments for Types and Extensions Source: https://github.com/airbnb/swift/blob/master/README.md Illustrates the use of MARK comments to organize type definitions and extensions. Follows conventions for marking types, conformances, and protocol extensions. ```swift // MARK: - GalaxyView final class GalaxyView: UIView { ... } // MARK: ContentConfigurableView extension GalaxyView: ContentConfigurableView { ... } // MARK: - Galaxy + SpaceThing, NamedObject extension Galaxy: SpaceThing, NamedObject { ... } ``` -------------------------------- ### Format Code Before Committing Source: https://github.com/airbnb/swift/blob/master/_autodocs/quick-start.md This sequence of commands demonstrates the workflow for formatting code before committing. It involves reviewing staged changes, auto-formatting, staging again, and then committing. ```bash git diff --cached # Review what you're about to commit swift package format # Auto-format git add . git commit -m "..." ``` -------------------------------- ### performCommand (Xcode XcodeCommandPlugin) Source: https://github.com/airbnb/swift/blob/master/_autodocs/api-reference.md Implementation for XcodeCommandPlugin, extracting target names, filtering project targets, collecting file paths, and delegating to the main implementation. ```APIDOC ## performCommand (Xcode XcodeCommandPlugin) ### Description Implements `XcodeCommandPlugin.performCommand` by extracting `--target` names, filtering Xcode project targets, collecting input file paths, filtering for `.swift` files, and delegating to the shared `performCommand(context:inputPaths:arguments:)` method. ### Signature ```swift @available(macOS 13, *) func performCommand(context: XcodePluginContext, arguments: [String]) throws ``` ### Parameters #### Path Parameters - `context` (XcodePluginContext) - Required - Xcode plugin context with project and target metadata - `arguments` ([String]) - Required - User-provided arguments (may include `--target`) ### Returns `Void` ### Throws `CommandError` on failure ``` -------------------------------- ### Test SwiftLint Individually Source: https://github.com/airbnb/swift/blob/master/_autodocs/errors.md Run SwiftLint separately to test its linting capabilities on your source code. Specify a configuration file using `--config` and enforce strict linting rules with `--strict`. ```bash # Test SwiftLint swiftlint /path/to/sources --config swiftlint.yml --strict ``` -------------------------------- ### Format Swift Package Source: https://github.com/airbnb/swift/blob/master/_autodocs/quick-start.md Format your Swift package code using the `swift package format` command. On the first run, you will be prompted for permission to write to the package directory. ```bash cd /path/to/your/package swift package format ``` -------------------------------- ### Direct tool invocation for formatting and linting Source: https://github.com/airbnb/swift/blob/master/_autodocs/overview.md Invoke the formatting tool directly, specifying paths to the Swift format and Swift lint executables. Optional flags for linting and Swift version are included. ```bash AirbnbSwiftFormatTool \ /path/to/sources \ --swift-format-path /path/to/swiftformat \ --swift-lint-path /path/to/swiftlint \ [--lint] \ [--swift-version 5.9] ``` -------------------------------- ### Using Void Instance Source: https://github.com/airbnb/swift/blob/master/README.md Illustrates the correct way to pass an instance of `Void` using the empty tuple `()` instead of `Void()`. This is the idiomatic Swift approach. ```swift let completion: (Result) -> Void // WRONG completion(.success(Void())) // RIGHT completion(.success(())) ``` -------------------------------- ### AirbnbSwiftFormatTool - run() Source: https://github.com/airbnb/swift/blob/master/_autodocs/api-reference.md Executes the Swift code formatting and linting pipeline. This method orchestrates the use of SwiftFormat and SwiftLint to format and check code style. ```APIDOC ## run() ### Description Executes the formatting pipeline: creates SwiftFormat command, runs SwiftFormat on input directories, runs SwiftLint with `--fix` to autocorrect violations, runs SwiftLint in lint-only mode to report remaining violations, and aggregates exit codes. ### Method `run()` ### Parameters #### Path Parameters - **directories** (array of strings) - Required - List of directories to format - **swiftFormatPath** (string) - Required - Absolute path to SwiftFormat binary - **swiftLintPath** (string) - Required - Absolute path to SwiftLint binary #### Query Parameters - **swiftFormatCachePath** (string) - Optional - Cache directory for SwiftFormat - **swiftLintCachePath** (string) - Optional - Cache directory for SwiftLint - **lint** (boolean) - Optional - If true, enables lint-only mode (no autocorrect). Defaults to `false`. - **log** (boolean) - Optional - If true, logs executed commands to stdout. Defaults to `false`. - **swiftFormatConfig** (string) - Optional - Path to SwiftFormat config file. Defaults to bundled `airbnb.swiftformat`. - **swiftLintConfig** (string) - Optional - Path to SwiftLint config file. Defaults to bundled `swiftlint.yml`. - **swiftVersion** (string) - Optional - Project's minimum Swift version (e.g., "5.9") ### Returns `Void` ### Throws `ExitCode` on failure ### Example ```swift do { var tool = AirbnbSwiftFormatTool.parseOrExit() try tool.run() } catch { print("Formatting failed: \(error)") exit(1) } ``` ``` -------------------------------- ### minimumSwiftVersion() Source: https://github.com/airbnb/swift/blob/master/_autodocs/api-reference.md Retrieves the lowest supported Swift version for the package by examining Package.swift and version-specific manifests. ```APIDOC ## minimumSwiftVersion() ### Description Computed property that collects all supported Swift versions (from Package.swift and version-specific manifests) and returns the minimum. ### Signature ```swift var minimumSwiftVersion: SwiftVersion ``` ### Returns The lowest supported Swift version for the package. ### Example ```swift let minVersion = package.minimumSwiftVersion print("\(minVersion.major).\(minVersion.minor)") // e.g., "5.6" ``` ``` -------------------------------- ### Custom Swift Version for Formatting Source: https://github.com/airbnb/swift/blob/master/site/src/plugin.md Provide a custom Swift version using the '--swift-version' flag if the plugin cannot infer it correctly from your Package.swift. ```shell $ swift package format --swift-version 6.2 ``` -------------------------------- ### Specify Swift Version for Formatting Source: https://github.com/airbnb/swift/blob/master/_autodocs/quick-start.md Override the auto-detected Swift version from `Package.swift` using the `--swift-version` flag to ensure compatibility with specific language features. ```swift // swift-tools-version:5.9 import PackageDescription let package = Package(...) ``` ```bash swift package format --swift-version 5.8 ```