diff --git a/Sources/Indexer/SourceFileCollector.swift b/Sources/Indexer/SourceFileCollector.swift index e6b793619..553db003a 100644 --- a/Sources/Indexer/SourceFileCollector.swift +++ b/Sources/Indexer/SourceFileCollector.swift @@ -4,6 +4,7 @@ import Logger import SourceGraph import SwiftIndexStore import SystemPackage +import Shared public struct SourceFileCollector { private let indexStorePaths: Set diff --git a/Sources/Indexer/JobPool.swift b/Sources/Shared/JobPool.swift similarity index 57% rename from Sources/Indexer/JobPool.swift rename to Sources/Shared/JobPool.swift index 59f05ff9e..f9eea9db8 100644 --- a/Sources/Indexer/JobPool.swift +++ b/Sources/Shared/JobPool.swift @@ -1,10 +1,13 @@ import Foundation -import Shared -struct JobPool { +public struct JobPool { let jobs: [Job] - func forEach(_ block: @escaping (Job) throws -> Void) throws { + public init(jobs: [Job]) { + self.jobs = jobs + } + + public func forEach(_ block: @escaping (Job) throws -> Void) throws { var error: Error? DispatchQueue.concurrentPerform(iterations: jobs.count) { idx in @@ -23,7 +26,8 @@ struct JobPool { } } - func flatMap(_ block: @escaping (Job) throws -> [Result]) throws -> [Result] { + /// Throwing variant + public func flatMap(_ block: @escaping (Job) throws -> [Result]) throws -> [Result] { var error: Error? var results: [Result] = [] let lock = UnfairLock() @@ -49,4 +53,21 @@ struct JobPool { return results } + + /// Non-throwing variant + public func flatMap(_ block: @escaping (Job) -> [Result]) -> [Result] { + var results: [Result] = [] + let lock = UnfairLock() + + DispatchQueue.concurrentPerform(iterations: jobs.count) { idx in + let job = jobs[idx] + let result = block(job) + + lock.perform { + results.append(contentsOf: result) + } + } + + return results + } } diff --git a/Sources/SourceGraph/Mutators/ProtocolConformanceReferenceBuilder.swift b/Sources/SourceGraph/Mutators/ProtocolConformanceReferenceBuilder.swift index 615609d8b..81704e75e 100644 --- a/Sources/SourceGraph/Mutators/ProtocolConformanceReferenceBuilder.swift +++ b/Sources/SourceGraph/Mutators/ProtocolConformanceReferenceBuilder.swift @@ -19,10 +19,10 @@ final class ProtocolConformanceReferenceBuilder: SourceGraphMutator { // MARK: - Private private func referenceConformingDeclarationsImplementedInSuperclass() -> Set { - var newReferences: Set = [] let protocols = graph.declarations(ofKind: .protocol) - for proto in protocols { + let newReferences = Set(JobPool(jobs: Array(protocols)).flatMap { [graph] proto in + var result: [Reference] = [] // Find all classes that implement this protocol. let conformingClasses = graph.references(to: proto) .reduce(into: Set()) { result, ref in @@ -66,13 +66,19 @@ final class ProtocolConformanceReferenceBuilder: SourceGraphMutator { ) reference.name = declInSuperclass.name reference.parent = unimplementedProtoDecl - graph.add(reference, from: unimplementedProtoDecl) - newReferences.insert(reference) + result.append(reference) } } } } } + return result + }) + // Perform mutations on the graph based on the calculated references + newReferences.forEach { + if let parent = $0.parent { + graph.add($0, from: parent) + } } return newReferences