Skip to content

Commit 323df9d

Browse files
committed
[Commands] Prototype swift fixit — a CLI for SwiftFixIt
1 parent 7571d6a commit 323df9d

File tree

8 files changed

+142
-0
lines changed

8 files changed

+142
-0
lines changed

Package.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,7 @@ let package = Package(
588588
"Workspace",
589589
"XCBuildSupport",
590590
"SwiftBuildSupport",
591+
"SwiftFixIt",
591592
] + swiftSyntaxDependencies(["SwiftIDEUtils"]),
592593
exclude: ["CMakeLists.txt", "README.md"],
593594
swiftSettings: swift6CompatibleExperimentalFeatures + [
@@ -745,6 +746,12 @@ let package = Package(
745746
"Workspace",
746747
]
747748
),
749+
.executableTarget(
750+
/** Deserializes diagnostics and applies fix-its */
751+
name: "swift-fixit",
752+
dependencies: ["Commands"],
753+
exclude: ["CMakeLists.txt"]
754+
),
748755

749756
// MARK: Support for Swift macros, should eventually move to a plugin-based solution
750757

Sources/Commands/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ add_library(Commands
4040
Snippets/Card.swift
4141
Snippets/Colorful.swift
4242
SwiftBuildCommand.swift
43+
SwiftFixItCommand.swift
4344
SwiftRunCommand.swift
4445
SwiftTestCommand.swift
4546
CommandWorkspaceDelegate.swift
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift open source project
4+
//
5+
// Copyright (c) 2025 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import struct ArgumentParser.Argument
14+
import protocol ArgumentParser.AsyncParsableCommand
15+
import struct ArgumentParser.CommandConfiguration
16+
import struct ArgumentParser.OptionGroup
17+
import protocol ArgumentParser.ParsableArguments
18+
19+
import struct Basics.AbsolutePath
20+
import var Basics.localFileSystem
21+
import struct Basics.SwiftVersion
22+
23+
import struct CoreCommands.LoggingOptions
24+
25+
import struct SwiftFixIt.SwiftFixIt
26+
27+
private struct Options: ParsableArguments {
28+
@OptionGroup(title: "Logging")
29+
var logging: LoggingOptions
30+
31+
@Argument(
32+
help: "",
33+
completion: .file(extensions: [".dia"])
34+
)
35+
var diagnosticFiles: [AbsolutePath] = []
36+
}
37+
38+
/// Deserializes `.dia` files and applies all fix-its in place.
39+
package struct SwiftFixitCommand: AsyncParsableCommand {
40+
package static var configuration = CommandConfiguration(
41+
commandName: "fixit",
42+
_superCommandName: "swift",
43+
abstract: "Deserialize diagnostics and apply fix-its",
44+
version: SwiftVersion.current.completeDisplayString,
45+
helpNames: [
46+
.short,
47+
.long,
48+
.customLong("help", withSingleDash: true),
49+
]
50+
)
51+
52+
@OptionGroup
53+
fileprivate var options: Options
54+
55+
package init() {}
56+
57+
package func run() async throws {
58+
if self.options.diagnosticFiles.isEmpty {
59+
return
60+
}
61+
62+
let swiftFixIt = try SwiftFixIt(diagnosticFiles: options.diagnosticFiles, fileSystem: localFileSystem)
63+
64+
try swiftFixIt.applyFixIts()
65+
}
66+
}

Sources/_InternalTestSupport/SwiftPMProduct.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public enum SwiftPM {
2929
case Run
3030
case experimentalSDK
3131
case sdk
32+
case fixit
3233
}
3334

3435
extension SwiftPM {
@@ -49,6 +50,8 @@ extension SwiftPM {
4950
return "swift-experimental-sdk"
5051
case .sdk:
5152
return "swift-sdk"
53+
case .fixit:
54+
return "swift-fixit"
5255
}
5356
}
5457

Sources/swift-fixit/CMakeLists.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# This source file is part of the Swift open source project
2+
#
3+
# Copyright (c) 2025 Apple Inc. and the Swift project authors
4+
# Licensed under Apache License v2.0 with Runtime Library Exception
5+
#
6+
# See http://swift.org/LICENSE.txt for license information
7+
# See http://swift.org/CONTRIBUTORS.txt for Swift project authors
8+
9+
add_executable(swift-fixit
10+
Entrypoint.swift)
11+
target_link_libraries(swift-test PRIVATE
12+
Commands)
13+
14+
target_compile_options(swift-test PRIVATE
15+
-parse-as-library)
16+
17+
install(TARGETS swift-fixit
18+
RUNTIME DESTINATION bin)

Sources/swift-fixit/Entrypoint.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift open source project
4+
//
5+
// Copyright (c) 2025 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import Commands
14+
15+
@main
16+
struct Entrypoint {
17+
static func main() async {
18+
await SwiftFixitCommand.main()
19+
}
20+
}

Sources/swift-package-manager/SwiftPM.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ struct SwiftPM {
5454
await PackageCollectionsCommand.main()
5555
case "swift-package-registry":
5656
await PackageRegistryCommand.main()
57+
case "swift-fixit":
58+
await SwiftFixitCommand.main()
5759
default:
5860
fatalError("swift-package-manager launched with unexpected name: \(execName ?? "(unknown)")")
5961
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift open source project
4+
//
5+
// Copyright (c) 2025 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import _InternalTestSupport
14+
@testable
15+
import Commands
16+
import XCTest
17+
18+
final class FixItCommandTests: CommandsTestCase {
19+
func testHelp() async throws {
20+
let stdout = try await SwiftPM.fixit.execute(["-help"]).stdout
21+
22+
XCTAssert(stdout.contains("USAGE: swift fixit"), stdout)
23+
XCTAssert(stdout.contains("-h, -help, --help"), stdout)
24+
}
25+
}

0 commit comments

Comments
 (0)