Skip to content

Reformat swift-format and enforce it on PRs. #830

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

Merged
merged 3 commits into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 0 additions & 1 deletion .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,5 @@ jobs:
name: Soundness
uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main
with:
format_check_enabled: false
license_header_check_enabled: false
license_header_check_project_name: "Swift.org"
18 changes: 18 additions & 0 deletions .swift-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"version": 1,
"lineLength": 120,
"indentation": {
"spaces": 2
},
"lineBreakBeforeEachArgument": true,
"indentConditionalCompilationBlocks": false,
"prioritizeKeepingFunctionOutputTogether": true,
"rules": {
"AlwaysUseLowerCamelCase": false,
"AmbiguousTrailingClosureOverload": false,
"NoBlockComments": false,
"OrderedImports": true,
"UseLetInEveryBoundCaseVariable": false,
"UseSynthesizedInitializer": false
}
}
9 changes: 3 additions & 6 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ let package = Package(
name: "swift-format",
platforms: [
.macOS("12.0"),
.iOS("13.0")
.iOS("13.0"),
],
products: [
.executable(
Expand Down Expand Up @@ -131,7 +131,7 @@ let package = Package(
.product(name: "SwiftSyntax", package: "swift-syntax"),
.product(name: "SwiftSyntaxBuilder", package: "swift-syntax"),
]
)
),
]
)

Expand Down Expand Up @@ -167,15 +167,12 @@ var dependencies: [Package.Dependency] {
}
}



// MARK: - Compute custom build settings

var swiftformatLinkSettings: [LinkerSetting] {
var swiftformatLinkSettings: [LinkerSetting] {
if installAction {
return [.unsafeFlags(["-no-toolchain-stdlib-rpath"], .when(platforms: [.linux, .android]))]
} else {
return []
}
}

34 changes: 17 additions & 17 deletions Plugins/FormatPlugin/plugin.swift
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
import PackagePlugin
import Foundation
import PackagePlugin

@main
struct FormatPlugin {
func format(tool: PluginContext.Tool, targetDirectories: [String], configurationFilePath: String?) throws {
let swiftFormatExec = URL(fileURLWithPath: tool.path.string)

var arguments: [String] = ["format"]

arguments.append(contentsOf: targetDirectories)

arguments.append(contentsOf: ["--recursive", "--parallel", "--in-place"])

if let configurationFilePath = configurationFilePath {
arguments.append(contentsOf: ["--configuration", configurationFilePath])
}

let process = try Process.run(swiftFormatExec, arguments: arguments)
process.waitUntilExit()

if process.terminationReason == .exit && process.terminationStatus == 0 {
print("Formatted the source code.")
}
else {
} else {
let problem = "\(process.terminationReason):\(process.terminationStatus)"
Diagnostics.error("swift-format invocation failed: \(problem)")
}
Expand All @@ -35,15 +34,16 @@ extension FormatPlugin: CommandPlugin {
arguments: [String]
) async throws {
let swiftFormatTool = try context.tool(named: "swift-format")

var argExtractor = ArgumentExtractor(arguments)
let targetNames = argExtractor.extractOption(named: "target")
let targetsToFormat = targetNames.isEmpty ? context.package.targets : try context.package.targets(named: targetNames)

let targetsToFormat =
targetNames.isEmpty ? context.package.targets : try context.package.targets(named: targetNames)

let configurationFilePath = argExtractor.extractOption(named: "swift-format-configuration").first
let sourceCodeTargets = targetsToFormat.compactMap{ $0 as? SourceModuleTarget }

let sourceCodeTargets = targetsToFormat.compactMap { $0 as? SourceModuleTarget }

try format(
tool: swiftFormatTool,
targetDirectories: sourceCodeTargets.map(\.directory.string),
Expand All @@ -58,10 +58,10 @@ import XcodeProjectPlugin
extension FormatPlugin: XcodeCommandPlugin {
func performCommand(context: XcodeProjectPlugin.XcodePluginContext, arguments: [String]) throws {
let swiftFormatTool = try context.tool(named: "swift-format")

var argExtractor = ArgumentExtractor(arguments)
let configurationFilePath = argExtractor.extractOption(named: "swift-format-configuration").first

try format(
tool: swiftFormatTool,
targetDirectories: [context.xcodeProject.directory.string],
Expand Down
30 changes: 15 additions & 15 deletions Plugins/LintPlugin/plugin.swift
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
import PackagePlugin
import Foundation
import PackagePlugin

@main
struct LintPlugin {
func lint(tool: PluginContext.Tool, targetDirectories: [String], configurationFilePath: String?) throws {
let swiftFormatExec = URL(fileURLWithPath: tool.path.string)

var arguments: [String] = ["lint"]

arguments.append(contentsOf: targetDirectories)

arguments.append(contentsOf: ["--recursive", "--parallel", "--strict"])

if let configurationFilePath = configurationFilePath {
arguments.append(contentsOf: ["--configuration", configurationFilePath])
}

let process = try Process.run(swiftFormatExec, arguments: arguments)
process.waitUntilExit()

if process.terminationReason == .exit && process.terminationStatus == 0 {
print("Linted the source code.")
}
else {
} else {
let problem = "\(process.terminationReason):\(process.terminationStatus)"
Diagnostics.error("swift-format invocation failed: \(problem)")
}
Expand All @@ -35,16 +34,17 @@ extension LintPlugin: CommandPlugin {
arguments: [String]
) async throws {
let swiftFormatTool = try context.tool(named: "swift-format")

// Extract the arguments that specify what targets to format.
var argExtractor = ArgumentExtractor(arguments)
let targetNames = argExtractor.extractOption(named: "target")

let targetsToFormat = targetNames.isEmpty ? context.package.targets : try context.package.targets(named: targetNames)

let targetsToFormat =
targetNames.isEmpty ? context.package.targets : try context.package.targets(named: targetNames)
let configurationFilePath = argExtractor.extractOption(named: "swift-format-configuration").first

let sourceCodeTargets = targetsToFormat.compactMap { $0 as? SourceModuleTarget }

try lint(
tool: swiftFormatTool,
targetDirectories: sourceCodeTargets.map(\.directory.string),
Expand All @@ -61,7 +61,7 @@ extension LintPlugin: XcodeCommandPlugin {
let swiftFormatTool = try context.tool(named: "swift-format")
var argExtractor = ArgumentExtractor(arguments)
let configurationFilePath = argExtractor.extractOption(named: "swift-format-configuration").first

try lint(
tool: swiftFormatTool,
targetDirectories: [context.xcodeProject.directory.string],
Expand Down
39 changes: 27 additions & 12 deletions Sources/SwiftFormat/API/Configuration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -278,9 +278,11 @@ public struct Configuration: Codable, Equatable {
self.version = try container.decodeIfPresent(Int.self, forKey: .version) ?? 1
guard version <= highestSupportedConfigurationVersion else {
throw DecodingError.dataCorruptedError(
forKey: .version, in: container,
forKey: .version,
in: container,
debugDescription:
"This version of the formatter does not support configuration version \(version).")
"This version of the formatter does not support configuration version \(version)."
)
}

// If we ever introduce a new version, this is where we should switch on the decoded version
Expand Down Expand Up @@ -328,30 +330,40 @@ public struct Configuration: Codable, Equatable {
?? defaults.prioritizeKeepingFunctionOutputTogether
self.indentConditionalCompilationBlocks =
try container.decodeIfPresent(Bool.self, forKey: .indentConditionalCompilationBlocks)
?? defaults.indentConditionalCompilationBlocks
?? defaults.indentConditionalCompilationBlocks
self.lineBreakAroundMultilineExpressionChainComponents =
try container.decodeIfPresent(
Bool.self, forKey: .lineBreakAroundMultilineExpressionChainComponents)
Bool.self,
forKey: .lineBreakAroundMultilineExpressionChainComponents
)
?? defaults.lineBreakAroundMultilineExpressionChainComponents
self.spacesAroundRangeFormationOperators =
try container.decodeIfPresent(
Bool.self, forKey: .spacesAroundRangeFormationOperators)
Bool.self,
forKey: .spacesAroundRangeFormationOperators
)
?? defaults.spacesAroundRangeFormationOperators
self.fileScopedDeclarationPrivacy =
try container.decodeIfPresent(
FileScopedDeclarationPrivacyConfiguration.self, forKey: .fileScopedDeclarationPrivacy)
FileScopedDeclarationPrivacyConfiguration.self,
forKey: .fileScopedDeclarationPrivacy
)
?? defaults.fileScopedDeclarationPrivacy
self.indentSwitchCaseLabels =
try container.decodeIfPresent(Bool.self, forKey: .indentSwitchCaseLabels)
?? defaults.indentSwitchCaseLabels
?? defaults.indentSwitchCaseLabels
self.noAssignmentInExpressions =
try container.decodeIfPresent(
NoAssignmentInExpressionsConfiguration.self, forKey: .noAssignmentInExpressions)
NoAssignmentInExpressionsConfiguration.self,
forKey: .noAssignmentInExpressions
)
?? defaults.noAssignmentInExpressions
self.multiElementCollectionTrailingCommas =
try container.decodeIfPresent(
Bool.self, forKey: .multiElementCollectionTrailingCommas)
?? defaults.multiElementCollectionTrailingCommas
Bool.self,
forKey: .multiElementCollectionTrailingCommas
)
?? defaults.multiElementCollectionTrailingCommas

self.reflowMultilineStringLiterals =
try container.decodeIfPresent(MultilineStringReflowBehavior.self, forKey: .reflowMultilineStringLiterals)
Expand Down Expand Up @@ -384,9 +396,12 @@ public struct Configuration: Codable, Equatable {
try container.encode(lineBreakBetweenDeclarationAttributes, forKey: .lineBreakBetweenDeclarationAttributes)
try container.encode(
lineBreakAroundMultilineExpressionChainComponents,
forKey: .lineBreakAroundMultilineExpressionChainComponents)
forKey: .lineBreakAroundMultilineExpressionChainComponents
)
try container.encode(
spacesAroundRangeFormationOperators, forKey: .spacesAroundRangeFormationOperators)
spacesAroundRangeFormationOperators,
forKey: .spacesAroundRangeFormationOperators
)
try container.encode(fileScopedDeclarationPrivacy, forKey: .fileScopedDeclarationPrivacy)
try container.encode(indentSwitchCaseLabels, forKey: .indentSwitchCaseLabels)
try container.encode(noAssignmentInExpressions, forKey: .noAssignmentInExpressions)
Expand Down
8 changes: 6 additions & 2 deletions Sources/SwiftFormat/API/Indent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ public enum Indent: Hashable, Codable {
throw DecodingError.dataCorrupted(
DecodingError.Context(
codingPath: decoder.codingPath,
debugDescription: "Only one of \"tabs\" or \"spaces\" may be specified"))
debugDescription: "Only one of \"tabs\" or \"spaces\" may be specified"
)
)
}
if let spacesCount = spacesCount {
self = .spaces(spacesCount)
Expand All @@ -50,7 +52,9 @@ public enum Indent: Hashable, Codable {
throw DecodingError.dataCorrupted(
DecodingError.Context(
codingPath: decoder.codingPath,
debugDescription: "One of \"tabs\" or \"spaces\" must be specified"))
debugDescription: "One of \"tabs\" or \"spaces\" must be specified"
)
)
}

public func encode(to encoder: Encoder) throws {
Expand Down
3 changes: 1 addition & 2 deletions Sources/SwiftFormat/API/Selection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public enum Selection {
self = .infinite
} else {
let ranges = offsetRanges.map {
AbsolutePosition(utf8Offset: $0.lowerBound) ..< AbsolutePosition(utf8Offset: $0.upperBound)
AbsolutePosition(utf8Offset: $0.lowerBound)..<AbsolutePosition(utf8Offset: $0.upperBound)
}
self = .ranges(ranges)
}
Expand All @@ -49,7 +49,6 @@ public enum Selection {
}
}


public extension Syntax {
/// - Returns: `true` if the node is _completely_ inside any range in the selection
func isInsideSelection(_ selection: Selection) -> Bool {
Expand Down
38 changes: 28 additions & 10 deletions Sources/SwiftFormat/API/SwiftFormatter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ public final class SwiftFormatter {
assumingFileURL: url,
selection: .infinite,
to: &outputStream,
parsingDiagnosticHandler: parsingDiagnosticHandler)
parsingDiagnosticHandler: parsingDiagnosticHandler
)
}

/// Formats the given Swift source code and writes the result to an output stream.
Expand Down Expand Up @@ -109,10 +110,16 @@ public final class SwiftFormatter {
source: source,
operatorTable: .standardOperators,
assumingFileURL: url,
parsingDiagnosticHandler: parsingDiagnosticHandler)
parsingDiagnosticHandler: parsingDiagnosticHandler
)
try format(
syntax: sourceFile, source: source, operatorTable: .standardOperators, assumingFileURL: url,
selection: selection, to: &outputStream)
syntax: sourceFile,
source: source,
operatorTable: .standardOperators,
assumingFileURL: url,
selection: selection,
to: &outputStream
)
}

/// Formats the given Swift syntax tree and writes the result to an output stream.
Expand All @@ -137,14 +144,24 @@ public final class SwiftFormatter {
/// be written.
/// - Throws: If an unrecoverable error occurs when formatting the code.
public func format<Output: TextOutputStream>(
syntax: SourceFileSyntax, source: String, operatorTable: OperatorTable,
assumingFileURL url: URL?, selection: Selection, to outputStream: inout Output
syntax: SourceFileSyntax,
source: String,
operatorTable: OperatorTable,
assumingFileURL url: URL?,
selection: Selection,
to outputStream: inout Output
) throws {
let assumedURL = url ?? URL(fileURLWithPath: "source")
let context = Context(
configuration: configuration, operatorTable: operatorTable, findingConsumer: findingConsumer,
fileURL: assumedURL, selection: selection, sourceFileSyntax: syntax, source: source,
ruleNameCache: ruleNameCache)
configuration: configuration,
operatorTable: operatorTable,
findingConsumer: findingConsumer,
fileURL: assumedURL,
selection: selection,
sourceFileSyntax: syntax,
source: source,
ruleNameCache: ruleNameCache
)
let pipeline = FormatPipeline(context: context)
let transformedSyntax = pipeline.rewrite(Syntax(syntax))

Expand All @@ -158,7 +175,8 @@ public final class SwiftFormatter {
source: source,
node: transformedSyntax,
printTokenStream: debugOptions.contains(.dumpTokenStream),
whitespaceOnly: false)
whitespaceOnly: false
)
outputStream.write(printer.prettyPrint())
}
}
Loading