Skip to content

Commit

Permalink
Depend on all swift source files, and find .safedi files at runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
dfed committed Dec 9, 2023
1 parent 20f8bbc commit 99a5ca1
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,15 @@ struct SafeDIGenerateDependencyTree: BuildToolPlugin {
}

let outputSwiftFile = context.pluginWorkDirectory.appending(subpath: "SafeDI.swift")
let targetDependencySafeDIOutputFiles = sourceTarget
let targetDependencySourceFiles = sourceTarget
.sourceModuleRecursiveDependencies
.flatMap {
$0
.sourceFiles(withSuffix: ".swift")
.map(\.path)
}

let instantiablePaths = sourceTarget
.sourceModuleRecursiveDependencies
.map {
context
Expand All @@ -31,8 +39,6 @@ struct SafeDIGenerateDependencyTree: BuildToolPlugin {
"\($0.name).safedi" // SafeDICollectInstantiables output file.
])
}

let instantiablePaths = targetDependencySafeDIOutputFiles
.map(\.string)
.compactMap { $0.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) }
let instantiablePathsArguments: [String] = if !instantiablePaths.isEmpty {
Expand All @@ -58,7 +64,7 @@ struct SafeDIGenerateDependencyTree: BuildToolPlugin {
executable: try context.tool(named: "SafeDIPlugin").path,
arguments: arguments,
environment: [:],
inputFiles: inputSwiftFiles + targetDependencySafeDIOutputFiles,
inputFiles: inputSwiftFiles + targetDependencySourceFiles,
outputFiles: [outputSwiftFile])
]
}
Expand Down Expand Up @@ -91,36 +97,44 @@ extension SafeDIGenerateDependencyTree: XcodeBuildToolPlugin {
// There are no Swift files in this module!
return []
}

let outputSwiftFile = context.pluginWorkDirectory.appending(subpath: "SafeDI.swift")
let targetDependencySafeDIOutputFiles = target
let targetDependencySourceFiles = target
.sourceModuleRecursiveDependencies
.map {
context
.pluginWorkDirectory
.removingLastComponent() // Remove `SafeDICollectInstantiables` from path.
.removingLastComponent() // Remove current module name from path.
.appending([
$0.displayName, // Dependency module name.
"SafeDICollectInstantiables", // SafeDICollectInstantiables working directory
"\($0.displayName).safedi" // SafeDICollectInstantiables output file.
])
}
+ target
.productRecursiveDependencies
.map {
context
.pluginWorkDirectory
.removingLastComponent() // Remove `SafeDICollectInstantiables` from path.
.removingLastComponent() // Remove current module name from path.
.appending([
$0.name, // Dependency module name.
"SafeDICollectInstantiables", // SafeDICollectInstantiables working directory
"\($0.name).safedi" // SafeDICollectInstantiables output file.
])
.flatMap {
$0
.inputFiles
.filter { $0.path.extension == "swift" }
.map(\.path)
}

let instantiablePaths = targetDependencySafeDIOutputFiles
let outputSwiftFile = context.pluginWorkDirectory.appending(subpath: "SafeDI.swift")
let instantiablePaths = (
target
.sourceModuleRecursiveDependencies
.map {
context
.pluginWorkDirectory
.removingLastComponent() // Remove `SafeDICollectInstantiables` from path.
.removingLastComponent() // Remove current module name from path.
.appending([
$0.displayName, // Dependency module name.
"SafeDICollectInstantiables", // SafeDICollectInstantiables working directory
"\($0.displayName).safedi" // SafeDICollectInstantiables output file.
])
}
+ target
.productRecursiveDependencies
.map {
context
.pluginWorkDirectory
.removingLastComponent() // Remove `SafeDICollectInstantiables` from path.
.removingLastComponent() // Remove current module name from path.
.appending([
$0.name, // Dependency module name.
"SafeDICollectInstantiables", // SafeDICollectInstantiables working directory
"\($0.name).safedi" // SafeDICollectInstantiables output file.
])
}
)
.map(\.string)
.compactMap { $0.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) }
let instantiablePathsArguments: [String] = if !instantiablePaths.isEmpty {
Expand All @@ -146,7 +160,7 @@ extension SafeDIGenerateDependencyTree: XcodeBuildToolPlugin {
executable: try context.tool(named: "SafeDIPlugin").path,
arguments: arguments,
environment: [:],
inputFiles: inputSwiftFiles + targetDependencySafeDIOutputFiles,
inputFiles: inputSwiftFiles + targetDependencySourceFiles,
outputFiles: [outputSwiftFile])
]
}
Expand Down
34 changes: 30 additions & 4 deletions Sources/SafeDIPlugin/SafeDIPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,11 @@ struct SafeDIPlugin: AsyncParsableCommand {
var dependencyTreeOutput: String?

func run() async throws {
let validInstantiableURLs = await Self.findValidInstantiablesURLs(possiblePaths: instantiablesPaths)
let output = try await Self.run(
swiftFileContent: try await loadSwiftFiles(),
dependentModuleNames: instantiablesPaths.map { $0.asFileURL.deletingPathExtension().lastPathComponent },
dependentInstantiables: Self.findSafeDIFulfilledTypes(atInstantiablesPaths: instantiablesPaths),
dependentModuleNames: validInstantiableURLs.map { $0.deletingPathExtension().lastPathComponent },
dependentInstantiables: Self.findSafeDIFulfilledTypes(atInstantiablesURLs: validInstantiableURLs),
buildDependencyTreeOutput: dependencyTreeOutput != nil
)

Expand Down Expand Up @@ -127,13 +128,38 @@ struct SafeDIPlugin: AsyncParsableCommand {
try JSONEncoder().encode(instantiables).write(toPath: path)
}

private static func findSafeDIFulfilledTypes(atInstantiablesPaths instantiablesPaths: [String]) async throws -> [[Instantiable]] {
private static func findValidInstantiablesURLs(possiblePaths: [String]) async -> [URL] {
await withTaskGroup(
of: Optional<URL>.self,
returning: [URL].self
) { taskGroup in
let instantiablesURLs = possiblePaths.map(\.asFileURL)
for instantiablesURL in instantiablesURLs {
taskGroup.addTask {
if let resourceIsReachable = try? instantiablesURL.checkResourceIsReachable(), resourceIsReachable {
instantiablesURL
} else {
nil
}
}
}
var validInstantiablesURLs = [URL]()
for await validInstantiablesURL in taskGroup {
if let validInstantiablesURL {
validInstantiablesURLs.append(validInstantiablesURL)
}
}

return validInstantiablesURLs
}
}

private static func findSafeDIFulfilledTypes(atInstantiablesURLs instantiablesURLs: [URL]) async throws -> [[Instantiable]] {
try await withThrowingTaskGroup(
of: [Instantiable].self,
returning: [[Instantiable]].self
) { taskGroup in
let decoder = ZippyJSONDecoder()
let instantiablesURLs = instantiablesPaths.map(\.asFileURL)
for instantiablesURL in instantiablesURLs {
taskGroup.addTask {
try decoder.decode([Instantiable].self, from: Data(contentsOf: instantiablesURL))
Expand Down

0 comments on commit 99a5ca1

Please sign in to comment.