SwiftLint/Source/swiftlint/Helpers/SwiftPMCompilationDB.swift

75 lines
2.4 KiB
Swift

import Foundation
import Yams
private struct SwiftPMCommand: Codable {
let tool: String
let module: String?
let sources: [String]?
let args: [String]?
let importPaths: [String]?
enum CodingKeys: String, CodingKey {
case tool
case module = "module-name"
case sources
case args = "other-args"
case importPaths = "import-paths"
}
}
private struct SwiftPMNode: Codable {}
private struct SwiftPMNodes: Codable {
let nodes: [String: SwiftPMNode]
}
struct SwiftPMCompilationDB: Codable {
private let commands: [String: SwiftPMCommand]
static func parse(yaml: Data) throws -> [File: Arguments] {
let decoder = YAMLDecoder()
let compilationDB: SwiftPMCompilationDB
if ProcessInfo.processInfo.environment["TEST_SRCDIR"] != nil {
// Running tests
let nodes = try decoder.decode(SwiftPMNodes.self, from: yaml)
let suffix = "/Source/swiftlint/"
let pathToReplace = Array(nodes.nodes.keys.filter({ node in
node.hasSuffix(suffix)
}))[0].dropLast(suffix.count - 1)
let stringFileContents = String(data: yaml, encoding: .utf8)!
.replacingOccurrences(of: pathToReplace, with: "")
compilationDB = try decoder.decode(Self.self, from: stringFileContents)
} else {
compilationDB = try decoder.decode(Self.self, from: yaml)
}
let swiftCompilerCommands = compilationDB.commands
.filter { $0.value.tool == "swift-compiler" }
let allSwiftSources = swiftCompilerCommands
.flatMap { $0.value.sources ?? [] }
.filter { $0.hasSuffix(".swift") }
return Dictionary(uniqueKeysWithValues: allSwiftSources.map { swiftSource in
let command = swiftCompilerCommands
.values
.first { $0.sources?.contains(swiftSource) == true }
guard let command,
let module = command.module,
let sources = command.sources,
let arguments = command.args,
let importPaths = command.importPaths
else {
return (swiftSource, [])
}
let args = ["-module-name", module] +
sources +
arguments.filteringCompilerArguments +
["-I"] + importPaths
return (swiftSource, args)
})
}
}