Skip to content

Commit b9f5805

Browse files
authored
Merge pull request swiftlang#887 from flashspys/iflet-example
Add new example: Migrate a Swift Codebase to the new if-let-Syntax
2 parents dab059c + 5411955 commit b9f5805

File tree

1 file changed

+59
-0
lines changed

1 file changed

+59
-0
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import Foundation
2+
import SwiftSyntax
3+
import SwiftParser
4+
5+
/// MigrateToNewIfLetSyntax will visit each `if` statement in the syntax tree
6+
/// replacing all "old style" optional bindings by the new shorter syntax available
7+
/// since Swift 5.7.
8+
///
9+
/// For example, it will turn:
10+
/// ```
11+
/// if let foo = foo {
12+
/// ...
13+
/// }
14+
/// ```
15+
/// into:
16+
/// ```
17+
/// if let foo {
18+
/// ...
19+
/// }
20+
class MigrateToNewIfLetSyntax: SyntaxRewriter {
21+
// Visit all `if` statements.
22+
override func visit(_ node: IfStmtSyntax) -> StmtSyntax {
23+
// Visit all conditions in the node.
24+
let newConditions = node.conditions.enumerated().map { (index, condition) in
25+
var conditionCopy = condition
26+
// Check if the condition is an optional binding ...
27+
if var binding = condition.condition.as(OptionalBindingConditionSyntax.self),
28+
// ... and has an initializer ...
29+
let initializer = binding.initializer,
30+
// ... and both sides of the assignment are the same identifiers.
31+
binding.pattern.withoutTrivia().description == initializer.value.withoutTrivia().description {
32+
// Remove the initializer ...
33+
binding.initializer = nil
34+
// ... and remove whitespace before the comma (in `if` statements with multiple conditions).
35+
if index != node.conditions.count - 1 {
36+
binding.pattern = binding.pattern.withoutTrailingTrivia()
37+
}
38+
conditionCopy.condition = Syntax(binding)
39+
}
40+
return conditionCopy
41+
}
42+
return StmtSyntax(node.withConditions(ConditionElementListSyntax(newConditions)))
43+
}
44+
45+
/// Utility function to migrate all swift files in a folder and its subfolders
46+
static func migrate(folderPath: String) {
47+
for case let fileURL as String in FileManager.default.enumerator(atPath: folderPath)! {
48+
if fileURL.hasSuffix("swift") {
49+
print("Rewriting", fileURL)
50+
let fullPath = folderPath + "/" + fileURL
51+
let tree = try! Parser.parse(source: String(data: FileManager.default.contents(atPath: fullPath)!, encoding: .utf8 )!)
52+
let newTree = MigrateToNewIfLetSyntax().visit(tree)
53+
try! newTree.description.write(toFile: fullPath, atomically: true, encoding: .utf8)
54+
}
55+
}
56+
}
57+
}
58+
59+
MigrateToNewIfLetSyntax.migrate(folderPath: "/path/to/folder")

0 commit comments

Comments
 (0)