mutating func loadAll()

in Sources/SwiftDocC/Infrastructure/Symbol Graph/SymbolGraphLoader.swift [48:128]


    mutating func loadAll() throws {
        let loadingLock = Lock()
        let decoder = JSONDecoder()

        var loadedGraphs = [URL: SymbolKit.SymbolGraph]()
        let graphLoader = GraphCollector()
        var loadError: Error?
        let bundle = self.bundle
        let dataProvider = self.dataProvider
        
        let loadGraphAtURL: (URL) -> Void = { symbolGraphURL in
            // Bail out in case a symbol graph has already errored
            guard loadError == nil else { return }
            
            do {
                // Load and decode a single symbol graph file
                let data = try dataProvider.contentsOfURL(symbolGraphURL, in: bundle)
                
                var symbolGraph: SymbolGraph
                
                switch decodingStrategy {
                case .concurrentlyAllFiles:
                    symbolGraph = try decoder.decode(SymbolGraph.self, from: data)
                case .concurrentlyEachFileInBatches:
                    symbolGraph = try SymbolGraphConcurrentDecoder.decode(data)
                }
                
                if let firstSymbolLanguage = symbolGraph.symbols.first?.value.identifier.interfaceLanguage {
                    guard FeatureFlags.current.isExperimentalObjectiveCSupportEnabled
                            || InterfaceLanguage.from(string: firstSymbolLanguage) == .swift
                    else {
                        return
                    }
                }

                // `moduleNameFor(_:at:)` is static because it's pure function.
                let (moduleName, _) = Self.moduleNameFor(symbolGraph, at: symbolGraphURL)
                // If the bundle provides availability defaults add symbol availability data.
                self.addDefaultAvailability(to: &symbolGraph, moduleName: moduleName)

                // Store the decoded graph in `loadedGraphs`
                loadingLock.sync {
                    loadedGraphs[symbolGraphURL] = symbolGraph
                    graphLoader.mergeSymbolGraph(symbolGraph, at: symbolGraphURL)
                }
            } catch {
                // If the symbol graph was invalid, store the error
                loadingLock.sync { loadError = error }
            }
        }
        
        // If we have symbol graph files for multiple platforms
        // load and decode each one on a separate thread.
        // This strategy benchmarks better when we have multiple
        // "larger" symbol graphs.
        #if os(macOS) || os(iOS)
        if bundle.symbolGraphURLs.filter({ !$0.path.contains("@") }).count > 1 {
            // There are multiple main symbol graphs, better parallelize all files decoding.
            decodingStrategy = .concurrentlyAllFiles
        }
        #endif
        
        switch decodingStrategy {
        case .concurrentlyAllFiles:
            // Concurrently load and decode all symbol graphs
            bundle.symbolGraphURLs.concurrentPerform(block: loadGraphAtURL)
            
        case .concurrentlyEachFileInBatches:
            // Serially load and decode all symbol graphs, each one in concurrent batches.
            bundle.symbolGraphURLs.forEach(loadGraphAtURL)
        }
        
        // In case any of the symbol graphs errors, re-throw the error.
        // We will not process unexpected file formats.
        if let loadError = loadError {
            throw loadError
        }
        
        self.symbolGraphs = loadedGraphs
        (self.unifiedGraphs, self.graphLocations) = graphLoader.finishLoading()
    }