@@ -112,71 +112,67 @@ package actor DocumentationLanguageService: LanguageService, Sendable {
112112
113113 package func hover( _ req: HoverRequest ) async throws -> HoverResponse ? {
114114 guard let sourceKitLSPServer else {
115- throw ResponseError . requestNotImplemented ( HoverRequest . self )
115+ throw ResponseError . unknown ( " Language server is shutting down " )
116116 }
117117
118- let uri = req. textDocument. uri
119- let snapshot = try documentManager. latestSnapshot ( uri)
118+ guard let snapshot = try ? documentManager. latestSnapshot ( req. textDocument. uri) ,
119+ snapshot. language == . swift,
120+ let workspace = await sourceKitLSPServer. workspaceForDocument ( uri: req. textDocument. uri) else {
121+ return nil
122+ }
120123
121- guard snapshot. language == . swift else {
122- throw ResponseError . requestNotImplemented ( HoverRequest . self)
124+ guard let ( symbolGraph, symbolUSR, overrideDocComments) = try ? await sourceKitLSPServer. primaryLanguageService (
125+ for: snapshot. uri,
126+ snapshot. language,
127+ in: workspace
128+ ) . symbolGraph ( for: snapshot, at: req. position) else {
129+ return nil
123130 }
124- guard let workspace = await sourceKitLSPServer. workspaceForDocument ( uri: req. textDocument. uri) else {
125- throw ResponseError . requestNotImplemented ( HoverRequest . self)
131+
132+ var moduleName : String ? = nil
133+ var catalogURL : URL ? = nil
134+ if let target = await workspace. buildServerManager. canonicalTarget ( for: req. textDocument. uri) {
135+ moduleName = await workspace. buildServerManager. moduleName ( for: target)
136+ catalogURL = await workspace. buildServerManager. doccCatalog ( for: target)
126137 }
127138
128- do {
129- let ( symbolGraph, symbolUSR, overrideDocComments) = try await sourceKitLSPServer. primaryLanguageService (
130- for: snapshot. uri,
131- snapshot. language,
132- in: workspace
133- ) . symbolGraph ( for: snapshot, at: req. position)
134-
135- var moduleName : String ? = nil
136- var catalogURL : URL ? = nil
137- if let target = await workspace. buildServerManager. canonicalTarget ( for: req. textDocument. uri) {
138- moduleName = await workspace. buildServerManager. moduleName ( for: target)
139- catalogURL = await workspace. buildServerManager. doccCatalog ( for: target)
140- }
141-
142- let doccResponse = try await documentationManager. renderDocCDocumentation (
143- symbolUSR: symbolUSR,
144- symbolGraph: symbolGraph,
145- overrideDocComments: overrideDocComments,
146- markupFile: nil ,
147- moduleName: moduleName,
148- catalogURL: catalogURL
149- )
150-
151- guard let renderNodeData = doccResponse. renderNode. data ( using: . utf8) else {
152- throw ResponseError . requestNotImplemented ( HoverRequest . self)
153- }
154- let renderNode = try JSONDecoder ( ) . decode ( RenderNode . self, from: renderNodeData)
155-
156- guard let markdown = renderNodeToMarkdown ( renderNode) else {
157- throw ResponseError . requestNotImplemented ( HoverRequest . self)
158- }
159- return HoverResponse ( contents: . markupContent( MarkupContent ( kind: . markdown, value: markdown) ) , range: nil )
160-
161- } catch {
162- throw ResponseError . requestNotImplemented ( HoverRequest . self)
139+ guard let doccResponse = try ? await documentationManager. renderDocCDocumentation (
140+ symbolUSR: symbolUSR,
141+ symbolGraph: symbolGraph,
142+ overrideDocComments: overrideDocComments,
143+ markupFile: nil ,
144+ moduleName: moduleName,
145+ catalogURL: catalogURL
146+ ) else {
147+ return nil
148+ }
149+
150+ guard let renderNodeData = try ? Data ( doccResponse. renderNode. utf8) ,
151+ let renderNode = try ? JSONDecoder ( ) . decode ( RenderNode . self, from: renderNodeData) ,
152+ let markdown = renderNode. markdown else {
153+ return nil
163154 }
155+
156+ return HoverResponse ( contents: . markupContent( MarkupContent ( kind: . markdown, value: markdown) ) , range: nil )
164157 }
165-
166- private func renderNodeToMarkdown( _ renderNode: RenderNode ) -> String ? {
158+ }
159+
160+ extension RenderNode {
161+ fileprivate var markdown : String ? {
167162 var result = " "
168163
169- let sections = renderNode . primaryContentSections
164+ let sections = primaryContentSections
170165 for section in sections {
171- if let declSection = section as? DeclarationsRenderSection ,
172- let declaration = declSection. declarations. first {
173- let sourceText = declaration. tokens. map { $0. text } . joined ( )
174- result += " ```swift \n \( sourceText) \n ``` \n "
166+ if let declSection = section as? DeclarationsRenderSection {
167+ for declaration in declSection. declarations {
168+ let sourceText = declaration. tokens. map ( \. text) . joined ( )
169+ result += " ```swift \n \( sourceText) \n ``` \n "
170+ }
175171 }
176172 }
177173
178- if let abstract = renderNode . abstract {
179- let abstractMarkdown = abstract. map { renderInlineContentToMarkdown ( $0 ) } . joined ( )
174+ if let abstract = abstract {
175+ let abstractMarkdown = abstract. map { $0 . markdown } . joined ( )
180176 if !abstractMarkdown. isEmpty {
181177 result += " \( abstractMarkdown) \n \n "
182178 }
@@ -185,13 +181,13 @@ package actor DocumentationLanguageService: LanguageService, Sendable {
185181 for section in sections {
186182 if let contentSection = section as? ContentRenderSection {
187183 for contentBlock in contentSection. content {
188- result += renderBlockContentToMarkdown ( contentBlock) + " \n "
184+ result += contentBlock. markdown + " \n "
189185 }
190186 } else if let parametersSection = section as? ParametersRenderSection {
191187 result += " ## Parameters \n "
192188 for param in parametersSection. parameters {
193189 result += " - ` \( param. name) `: "
194- let paramContent = param. content. compactMap { renderBlockContentToMarkdown ( $0 ) . trimmingCharacters ( in: . whitespacesAndNewlines) }
190+ let paramContent = param. content. compactMap { $0 . markdown . trimmingCharacters ( in: . whitespacesAndNewlines) }
195191 result += paramContent. joined ( separator: " " ) + " \n "
196192 }
197193 result += " \n "
@@ -201,16 +197,18 @@ package actor DocumentationLanguageService: LanguageService, Sendable {
201197 let finalResult = result. trimmingCharacters ( in: . whitespacesAndNewlines)
202198 return finalResult. isEmpty ? nil : finalResult
203199 }
204-
205- private func renderInlineContentToMarkdown( _ content: RenderInlineContent ) -> String {
206- switch content {
200+ }
201+
202+ extension RenderInlineContent {
203+ fileprivate var markdown : String {
204+ switch self {
207205 case . text( let text) : return text
208206 case . codeVoice( let code) : return " ` \( code) ` "
209- case . strong( let inline) : return " ** \( inline. map ( renderInlineContentToMarkdown ) . joined ( ) ) ** "
210- case . emphasis( let inline) : return " * \( inline. map ( renderInlineContentToMarkdown ) . joined ( ) ) * "
207+ case . strong( let inline) : return " ** \( inline. map ( \ . markdown ) . joined ( ) ) ** "
208+ case . emphasis( let inline) : return " * \( inline. map ( \ . markdown ) . joined ( ) ) * "
211209 case . reference( _, _, let overridingTitle, let overridingTitleInlineContent) :
212210 if let titleContent = overridingTitleInlineContent {
213- return titleContent. map ( renderInlineContentToMarkdown ) . joined ( )
211+ return titleContent. map ( \ . markdown ) . joined ( )
214212 } else if let title = overridingTitle {
215213 return " ` \( title) ` "
216214 } else {
@@ -219,11 +217,13 @@ package actor DocumentationLanguageService: LanguageService, Sendable {
219217 default : return " "
220218 }
221219 }
222-
223- private func renderBlockContentToMarkdown( _ content: RenderBlockContent ) -> String {
224- switch content {
220+ }
221+
222+ extension RenderBlockContent {
223+ fileprivate var markdown : String {
224+ switch self {
225225 case . paragraph( let p) :
226- return p. inlineContent. map ( renderInlineContentToMarkdown ) . joined ( ) + " \n "
226+ return p. inlineContent. map ( \ . markdown ) . joined ( ) + " \n "
227227 case . codeListing( _) :
228228 return " "
229229 case . heading( let h) :
0 commit comments