-
Notifications
You must be signed in to change notification settings - Fork 434
/
Copy pathFormatter.step10.swift
79 lines (72 loc) · 2.02 KB
/
Formatter.step10.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import Foundation
import SwiftParser
import SwiftSyntax
@main struct ImportFormatter {
static func main() {
guard CommandLine.arguments.count == 2 else {
print("Not enough arguments!")
return
}
let filePath = CommandLine.arguments[1]
guard FileManager.default.fileExists(atPath: filePath) else {
print("File doesn't exist at path: \(filePath)")
return
}
guard let file = try? String(contentsOfFile: filePath) else {
print("File at path isn't readable: \(filePath)")
return
}
let formattedFile = ImportFormatter().formatImports(in: file)
print(formattedFile)
}
func formatImports(in file: String) -> SourceFileSyntax {
let sourceFile = Parser.parse(source: file)
var items = classifyItems(in: sourceFile)
let pivotPoint = items.partition { item in
switch item {
case .import(_, _):
return false
case .other(_):
return true
}
}
items[..<pivotPoint]
.sort { lhs, rhs in
guard
case .import(let lhsImport, _) = lhs,
case .import(let rhsImport, _) = rhs
else {
fatalError("Partition must only contain import items!")
}
return lhsImport.path.description < rhsImport.path.description
}
let formattedStatements = items.map { item in
switch item {
case .import(_, let statement):
return statement
case .other(let statement):
return statement
}
}
return
sourceFile
.with(\.statements, CodeBlockItemListSyntax(formattedStatements))
}
enum Item {
case `import`(ImportDeclSyntax, CodeBlockItemSyntax)
case other(CodeBlockItemSyntax)
}
func classifyItems(in file: SourceFileSyntax) -> [Item] {
file
.statements
.map { statement in
if case .decl(let decl) = statement.item,
let `import` = decl.as(ImportDeclSyntax.self)
{
return .import(`import`, statement)
} else {
return .other(statement)
}
}
}
}