@@ -218,7 +218,7 @@ public class DocumentationContext {
218218 self . linkResolver = LinkResolver ( dataProvider: dataProvider)
219219
220220 ResolvedTopicReference . enableReferenceCaching ( for: inputs. id)
221- try register ( )
221+ try await register ( )
222222 }
223223
224224 /// Perform semantic analysis on a given `document` at a given `source` location and append any problems found to `problems`.
@@ -1931,7 +1931,7 @@ public class DocumentationContext {
19311931 /**
19321932 Register a documentation bundle with this context.
19331933 */
1934- private func register( ) throws {
1934+ private func register( ) async throws {
19351935 try shouldContinueRegistration ( )
19361936
19371937 let currentFeatureFlags : FeatureFlags ?
@@ -1963,111 +1963,61 @@ public class DocumentationContext {
19631963 }
19641964 }
19651965
1966- // Note: Each bundle is registered and processed separately.
1967- // Documents and symbols may both reference each other so the bundle is registered in 4 steps
1968-
1969- // In the bundle discovery phase all tasks run in parallel as they don't depend on each other.
1970- let discoveryGroup = DispatchGroup ( )
1971- let discoveryQueue = DispatchQueue ( label: " org.swift.docc.Discovery " , qos: . unspecified, attributes: . concurrent, autoreleaseFrequency: . workItem)
1972-
1973- let discoveryError = Synchronized < ( any Error ) ? > ( nil )
1966+ // Documents and symbols may both reference each other so the inputs is registered in 4 steps
19741967
1975- // Load all bundle symbol graphs into the loader.
1976- var symbolGraphLoader : SymbolGraphLoader !
1977- var hierarchyBasedResolver : PathHierarchyBasedLinkResolver !
1978-
1979- discoveryGroup. async ( queue: discoveryQueue) { [ unowned self] in
1980- symbolGraphLoader = SymbolGraphLoader (
1968+ // Load symbol information and construct data structures that only rely on symbol information.
1969+ async let loadSymbols = { [ signposter, inputs, dataProvider, configuration] in
1970+ var symbolGraphLoader = SymbolGraphLoader (
19811971 bundle: inputs,
19821972 dataProvider: dataProvider,
19831973 symbolGraphTransformer: configuration. convertServiceConfiguration. symbolGraphTransformer
19841974 )
19851975
1986- do {
1987- try signposter . withIntervalSignpost ( " Load symbols " , id : signposter . makeSignpostID ( ) ) {
1976+ try signposter . withIntervalSignpost ( " Load symbols " , id : signposter . makeSignpostID ( ) ) {
1977+ try autoreleasepool {
19881978 try symbolGraphLoader. loadAll ( )
19891979 }
1990- hierarchyBasedResolver = signposter. withIntervalSignpost ( " Build PathHierarchy " , id: signposter. makeSignpostID ( ) ) {
1980+ }
1981+ try shouldContinueRegistration ( )
1982+ let hierarchyBasedResolver = signposter. withIntervalSignpost ( " Build PathHierarchy " , id: signposter. makeSignpostID ( ) ) {
1983+ autoreleasepool {
19911984 PathHierarchyBasedLinkResolver ( pathHierarchy: PathHierarchy (
19921985 symbolGraphLoader: symbolGraphLoader,
19931986 bundleName: urlReadablePath ( inputs. displayName) ,
19941987 knownDisambiguatedPathComponents: configuration. convertServiceConfiguration. knownDisambiguatedSymbolPathComponents
19951988 ) )
19961989 }
1997-
1998- self . snippetResolver = SnippetResolver ( symbolGraphLoader: symbolGraphLoader)
1999- } catch {
2000- // Pipe the error out of the dispatch queue.
2001- discoveryError. sync ( {
2002- if $0 == nil { $0 = error }
2003- } )
20041990 }
2005- }
1991+
1992+ let snippetResolver = SnippetResolver ( symbolGraphLoader: symbolGraphLoader)
1993+
1994+ return ( symbolGraphLoader, hierarchyBasedResolver, snippetResolver)
1995+ } ( )
20061996
2007- // First, all the resources are added since they don't reference anything else.
2008- discoveryGroup. async ( queue: discoveryQueue) { [ unowned self] in
2009- do {
2010- try signposter. withIntervalSignpost ( " Load resources " , id: signposter. makeSignpostID ( ) ) {
2011- try self . registerMiscResources ( )
2012- }
2013- } catch {
2014- // Pipe the error out of the dispatch queue.
2015- discoveryError. sync ( {
2016- if $0 == nil { $0 = error }
2017- } )
1997+ // Load resources like images and videos
1998+ async let loadResources : Void = try signposter. withIntervalSignpost ( " Load resources " , id: signposter. makeSignpostID ( ) ) {
1999+ try autoreleasepool {
2000+ try self . registerMiscResources ( )
20182001 }
20192002 }
20202003
2021- // Second, all the documents and symbols are added.
2022- //
2023- // Note: Documents and symbols may look up resources at this point but shouldn't lookup other documents or
2024- // symbols or attempt to resolve links/references since the topic graph may not contain all documents
2025- // or all symbols yet.
2026- var result : (
2027- tutorialTableOfContentsResults: [ SemanticResult < TutorialTableOfContents > ] ,
2028- tutorials: [ SemanticResult < Tutorial > ] ,
2029- tutorialArticles: [ SemanticResult < TutorialArticle > ] ,
2030- articles: [ SemanticResult < Article > ] ,
2031- documentationExtensions: [ SemanticResult < Article > ]
2032- ) !
2033-
2034- discoveryGroup. async ( queue: discoveryQueue) { [ unowned self] in
2035- do {
2036- result = try signposter. withIntervalSignpost ( " Load documents " , id: signposter. makeSignpostID ( ) ) {
2037- try self . registerDocuments ( )
2038- }
2039- } catch {
2040- // Pipe the error out of the dispatch queue.
2041- discoveryError. sync ( {
2042- if $0 == nil { $0 = error }
2043- } )
2004+ // Load documents
2005+ async let loadDocuments = try signposter. withIntervalSignpost ( " Load documents " , id: signposter. makeSignpostID ( ) ) {
2006+ try autoreleasepool {
2007+ try self . registerDocuments ( )
20442008 }
20452009 }
20462010
2047- discoveryGroup. async ( queue: discoveryQueue) { [ unowned self] in
2048- do {
2049- try signposter. withIntervalSignpost ( " Load external resolvers " , id: signposter. makeSignpostID ( ) ) {
2050- try linkResolver. loadExternalResolvers ( dependencyArchives: configuration. externalDocumentationConfiguration. dependencyArchives)
2051- }
2052- } catch {
2053- // Pipe the error out of the dispatch queue.
2054- discoveryError. sync ( {
2055- if $0 == nil { $0 = error }
2056- } )
2011+ // Load any external resolvers
2012+ async let loadExternalResolvers : Void = try signposter. withIntervalSignpost ( " Load external resolvers " , id: signposter. makeSignpostID ( ) ) {
2013+ try autoreleasepool {
2014+ try linkResolver. loadExternalResolvers ( dependencyArchives: configuration. externalDocumentationConfiguration. dependencyArchives)
20572015 }
20582016 }
20592017
2060- discoveryGroup. wait ( )
2061-
2062- try shouldContinueRegistration ( )
2063-
2064- // Re-throw discovery errors
2065- if let encounteredError = discoveryError. sync ( { $0 } ) {
2066- throw encounteredError
2067- }
2068-
20692018 // All discovery went well, process the inputs.
2070- let ( tutorialTableOfContentsResults, tutorials, tutorialArticles, allArticles, documentationExtensions) = result
2019+ let ( tutorialTableOfContentsResults, tutorials, tutorialArticles, allArticles, documentationExtensions) = try await loadDocuments
2020+ try shouldContinueRegistration ( )
20712021 var ( otherArticles, rootPageArticles) = splitArticles ( allArticles)
20722022
20732023 let globalOptions = ( allArticles + documentationExtensions) . compactMap { article in
@@ -2107,7 +2057,10 @@ public class DocumentationContext {
21072057 options = globalOptions. first
21082058 }
21092059
2060+ let ( symbolGraphLoader, hierarchyBasedResolver, snippetResolver) = try await loadSymbols
2061+ try shouldContinueRegistration ( )
21102062 self . linkResolver. localResolver = hierarchyBasedResolver
2063+ self . snippetResolver = snippetResolver
21112064 hierarchyBasedResolver. addMappingForRoots ( bundle: inputs)
21122065 for tutorial in tutorials {
21132066 hierarchyBasedResolver. addTutorial ( tutorial)
@@ -2120,9 +2073,10 @@ public class DocumentationContext {
21202073 }
21212074
21222075 registerRootPages ( from: rootPageArticles)
2076+
21232077 try registerSymbols ( symbolGraphLoader: symbolGraphLoader, documentationExtensions: documentationExtensions)
21242078 // We don't need to keep the loader in memory after we've registered all symbols.
2125- symbolGraphLoader = nil
2079+ _ = consume symbolGraphLoader
21262080
21272081 try shouldContinueRegistration ( )
21282082
@@ -2149,12 +2103,17 @@ public class DocumentationContext {
21492103 try shouldContinueRegistration ( )
21502104 }
21512105
2106+ _ = try await loadExternalResolvers
2107+
21522108 // Third, any processing that relies on resolving other content is done, mainly resolving links.
21532109 preResolveExternalLinks ( semanticObjects:
21542110 tutorialTableOfContentsResults. map ( referencedSemanticObject) +
21552111 tutorials. map ( referencedSemanticObject) +
21562112 tutorialArticles. map ( referencedSemanticObject) )
21572113
2114+ // References to resources aren't used until the links are resolved
2115+ _ = try await loadResources
2116+
21582117 resolveLinks (
21592118 tutorialTableOfContents: tutorialTableOfContentsResults,
21602119 tutorials: tutorials,
0 commit comments