-
Notifications
You must be signed in to change notification settings - Fork 4.2k
/
main.swift
105 lines (77 loc) · 3.51 KB
/
main.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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
//
// main.swift
// Preprocessor
//
// Created by Krunoslav Zaher on 4/22/15.
// Copyright © 2015 Krunoslav Zaher. All rights reserved.
//
import Foundation
if CommandLine.argc != 3 {
print("./Preprocessor <source-files-root> <derived-data> ")
exit(-1)
}
let sourceFilesRoot = CommandLine.arguments[1]
let derivedData = CommandLine.arguments[2]
let fileManager = FileManager()
func escape(value: String) -> String {
let escapedString = value.replacingOccurrences(of: "\n", with: "\\n")
let escapedString1 = escapedString.replacingOccurrences(of: "\r", with: "\\r")
let escapedString2 = escapedString1.replacingOccurrences(of: "\"", with: "\\\"")
return "\"\(escapedString2)\""
}
func processFile(path: String, outputPath: String) -> String {
let url = URL(fileURLWithPath: path)
let rawContent = try! Data(contentsOf: url)
let content = String(data: rawContent, encoding: String.Encoding.utf8)
guard let components = content?.components(separatedBy: "<%") else { return "" }
var functionContentComponents: [String] = []
functionContentComponents.append("var components: [String] = [\"// This file is autogenerated. Take a look at `Preprocessor` target in RxSwift project \\n\"]\n")
functionContentComponents.append("components.append(\(escape(value: components[0])))\n")
for codePlusSuffix in (components[1 ..< components.count]) {
let codePlusSuffixSeparated = codePlusSuffix.components(separatedBy: "%>")
if codePlusSuffixSeparated.count != 2 {
fatalError("Error in \(path) near \(codePlusSuffix)")
}
let code = codePlusSuffixSeparated[0]
let suffix = codePlusSuffixSeparated[1]
if code.hasPrefix("=") {
functionContentComponents.append("components.append(String(\(String(code[code.index(after: code.startIndex) ..< code.endIndex]))))\n")
}
else {
functionContentComponents.append("\(code)\n")
}
functionContentComponents.append("components.append(\(escape(value: suffix)));\n")
}
functionContentComponents.append("try! components.joined(separator:\"\").write(toFile:\"\(outputPath)\", atomically: false, encoding: String.Encoding.utf8)")
return functionContentComponents.joined(separator: "")
}
func runCommand(path: String) {
_ = ProcessInfo().processIdentifier
let process = Process()
process.launchPath = "/bin/bash"
process.arguments = ["-c", "xcrun swift \"\(path)\""]
process.launch()
process.waitUntilExit()
if process.terminationReason != .exit {
exit(-1)
}
}
let files = try fileManager.subpathsOfDirectory(atPath: sourceFilesRoot)
var generateAllFiles = ["// Generated code\n", "import Foundation\n"]
for file in files {
if ((file as NSString).pathExtension) != "tt" {
continue
}
print(file)
let path = (sourceFilesRoot as NSString).appendingPathComponent(file as String)
let endIndex = path.index(before: path.index(before: path.index(before: path.endIndex)))
let outputPath = String(path[path.startIndex ..< endIndex]) + ".swift"
generateAllFiles.append("_ = { () -> Void in\n\(processFile(path: path, outputPath: outputPath))\n}()\n")
}
let script = generateAllFiles.joined(separator: "")
let scriptPath = (derivedData as NSString).appendingPathComponent("_preprocessor.sh")
do {
try script.write(toFile: scriptPath, atomically: true, encoding: String.Encoding.utf8)
} catch _ {
}
runCommand(path: scriptPath)