Skip to content

Commit 49b3f53

Browse files
move SwiftDocC related functionality into its own module
1 parent 24118eb commit 49b3f53

17 files changed

+402
-328
lines changed

Package.swift

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,24 @@ var targets: [Target] = [
214214
swiftSettings: globalSwiftSettings
215215
),
216216

217+
// MARK: DocCDocumentation
218+
219+
.target(
220+
name: "DocCDocumentation",
221+
dependencies: [
222+
"BuildServerProtocol",
223+
"BuildSystemIntegration",
224+
"LanguageServerProtocol",
225+
"SemanticIndex",
226+
"SKLogging",
227+
"SKUtilities",
228+
"SwiftExtensions",
229+
.product(name: "SwiftDocC", package: "swift-docc"),
230+
],
231+
exclude: ["CMakeLists.txt"],
232+
swiftSettings: globalSwiftSettings
233+
),
234+
217235
// MARK: InProcessClient
218236

219237
.target(
@@ -474,6 +492,7 @@ var targets: [Target] = [
474492
dependencies: [
475493
"BuildServerProtocol",
476494
"BuildSystemIntegration",
495+
"DocCDocumentation",
477496
"LanguageServerProtocol",
478497
"LanguageServerProtocolExtensions",
479498
"LanguageServerProtocolJSONRPC",
@@ -485,12 +504,11 @@ var targets: [Target] = [
485504
"SwiftExtensions",
486505
"ToolchainRegistry",
487506
"TSCExtensions",
488-
.product(name: "SwiftDocC", package: "swift-docc"),
489-
.product(name: "SymbolKit", package: "swift-docc-symbolkit"),
490-
.product(name: "Markdown", package: "swift-markdown"),
491507
.product(name: "IndexStoreDB", package: "indexstore-db"),
492508
.product(name: "Crypto", package: "swift-crypto"),
509+
.product(name: "Markdown", package: "swift-markdown"),
493510
.product(name: "SwiftToolsSupport-auto", package: "swift-tools-support-core"),
511+
.product(name: "SymbolKit", package: "swift-docc-symbolkit"),
494512
]
495513
+ swiftPMDependency([
496514
.product(name: "SwiftPM-auto", package: "swift-package-manager")

Sources/SourceKitLSP/Documentation/DocCWorkspaceExtensions.swift renamed to Sources/DocCDocumentation/BuildSystemIntegrationExtensions.swift

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,49 +10,39 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
#if canImport(SwiftDocC)
1413
import BuildServerProtocol
15-
import BuildSystemIntegration
16-
import Foundation
17-
import LanguageServerProtocol
14+
package import BuildSystemIntegration
15+
package import Foundation
16+
package import LanguageServerProtocol
1817

19-
extension Workspace {
20-
private var documentationManager: DocumentationManager {
21-
get throws {
22-
guard let sourceKitLSPServer else {
23-
throw ResponseError.unknown("Connection to the editor closed")
24-
}
25-
return sourceKitLSPServer.documentationManager
26-
}
27-
}
28-
29-
func findModuleName(for document: DocumentURI) async -> String? {
30-
guard let target = await buildSystemManager.canonicalTarget(for: document) else {
18+
package extension BuildSystemManager {
19+
func moduleName(for document: DocumentURI) async -> String? {
20+
guard let target = await canonicalTarget(for: document) else {
3121
return nil
3222
}
33-
let sourceFiles = (try? await buildSystemManager.sourceFiles(in: [target]).flatMap(\.sources)) ?? []
23+
let sourceFiles = (try? await sourceFiles(in: [target]).flatMap(\.sources)) ?? []
3424
for sourceFile in sourceFiles {
35-
let language = await buildSystemManager.defaultLanguage(for: sourceFile.uri, in: target)
25+
let language = await defaultLanguage(for: sourceFile.uri, in: target)
3626
guard language == .swift else {
3727
continue
3828
}
39-
if let moduleName = await buildSystemManager.moduleName(for: sourceFile.uri, in: target) {
29+
if let moduleName = await moduleName(for: sourceFile.uri, in: target) {
4030
return moduleName
4131
}
4232
}
4333
return nil
4434
}
4535

46-
func findDocCCatalog(for document: DocumentURI) async -> URL? {
47-
guard let target = await buildSystemManager.canonicalTarget(for: document) else {
36+
func doccCatalog(for document: DocumentURI) async -> URL? {
37+
guard let target = await canonicalTarget(for: document) else {
4838
return nil
4939
}
50-
let sourceFiles = (try? await buildSystemManager.sourceFiles(in: [target]).flatMap(\.sources)) ?? []
40+
let sourceFiles = (try? await sourceFiles(in: [target]).flatMap(\.sources)) ?? []
5141
return sourceFiles.compactMap(\.uri.fileURL?.doccCatalogURL).first
5242
}
5343
}
5444

55-
extension URL {
45+
package extension URL {
5646
var doccCatalogURL: URL? {
5747
var pathComponents = self.pathComponents
5848
var result = self
@@ -66,4 +56,3 @@ extension URL {
6656
return nil
6757
}
6858
}
69-
#endif

Sources/SourceKitLSP/Documentation/DocCCatalogIndexManager.swift renamed to Sources/DocCDocumentation/DocCCatalogIndexManager.swift

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,19 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
package import Foundation
14+
15+
package protocol DocCCatalogIndex: Sendable {
16+
func documentationExtension(for symbolLink: any DocCSymbolLink) -> URL?
17+
}
18+
1319
#if canImport(SwiftDocC)
14-
import Foundation
1520
@preconcurrency import SwiftDocC
1621
import SwiftExtensions
1722

1823
final actor DocCCatalogIndexManager {
1924
private let server: DocCServer
20-
private var catalogToIndexMap = [URL: Result<DocCCatalogIndex, DocCIndexError>]()
25+
private var catalogToIndexMap = [URL: Result<DocCCatalogIndexImpl, DocCIndexError>]()
2126

2227
init(server: DocCServer) {
2328
self.server = server
@@ -32,11 +37,11 @@ final actor DocCCatalogIndexManager {
3237
}
3338
}
3439

35-
func index(for catalogURL: URL) async throws(DocCIndexError) -> DocCCatalogIndex {
40+
func index(for catalogURL: URL) async throws(DocCIndexError) -> DocCCatalogIndexImpl {
3641
if let existingCatalog = catalogToIndexMap[catalogURL] {
3742
return try existingCatalog.get()
3843
}
39-
let catalogIndexResult: Result<DocCCatalogIndex, DocCIndexError>
44+
let catalogIndexResult: Result<DocCCatalogIndexImpl, DocCIndexError>
4045
do {
4146
let convertResponse = try await server.convert(
4247
externalIDsToConvert: [],
@@ -62,37 +67,37 @@ final actor DocCCatalogIndexManager {
6267
Result { try JSONDecoder().decode(RenderReferenceStore.self, from: renderReferenceStoreData) }
6368
.flatMapError { .failure(.decodingFailure($0)) }
6469
}
65-
.map { DocCCatalogIndex(from: $0) }
70+
.map { DocCCatalogIndexImpl(from: $0) }
6671
} catch {
67-
catalogIndexResult = .failure(.serverError(error))
72+
catalogIndexResult = .failure(.internalError(error))
6873
}
6974
catalogToIndexMap[catalogURL] = catalogIndexResult
7075
return try catalogIndexResult.get()
7176
}
7277
}
7378

7479
/// Represents a potential error that the ``DocCCatalogIndexManager`` could encounter while indexing
75-
enum DocCIndexError: LocalizedError {
80+
package enum DocCIndexError: LocalizedError {
7681
case decodingFailure(Error)
77-
case serverError(DocCServerError)
82+
case internalError(LocalizedError)
7883
case unexpectedlyNilRenderReferenceStore
7984

80-
var errorDescription: String? {
85+
package var errorDescription: String? {
8186
switch self {
8287
case .decodingFailure(let decodingError):
8388
return "Failed to decode a received message: \(decodingError.localizedDescription)"
84-
case .serverError(let serverError):
85-
return "DocC server failed to convert the catalog: \(serverError.localizedDescription)"
89+
case .internalError(let internalError):
90+
return "An internal error occurred: \(internalError.localizedDescription)"
8691
case .unexpectedlyNilRenderReferenceStore:
8792
return "Did not receive a RenderReferenceStore from the DocC server"
8893
}
8994
}
9095
}
9196

92-
struct DocCCatalogIndex: Sendable {
97+
package struct DocCCatalogIndexImpl: DocCCatalogIndex {
9398
private let assetReferenceToDataAsset: [String: DataAsset]
9499
private let fuzzyAssetReferenceToDataAsset: [String: DataAsset]
95-
private let documentationExtensionToSourceURL: [DocCSymbolLink: URL]
100+
private let documentationExtensionToSourceURL: [DocCSymbolLinkImpl: URL]
96101
let articlePathToSourceURLAndReference: [String: (URL, TopicRenderReference)]
97102
let tutorialPathToSourceURLAndReference: [String: (URL, TopicRenderReference)]
98103
let tutorialOverviewPathToSourceURLAndReference: [String: (URL, TopicRenderReference)]
@@ -101,8 +106,11 @@ struct DocCCatalogIndex: Sendable {
101106
assetReferenceToDataAsset[assetReference.assetName] ?? fuzzyAssetReferenceToDataAsset[assetReference.assetName]
102107
}
103108

104-
func documentationExtension(for symbolLink: DocCSymbolLink) -> URL? {
105-
documentationExtensionToSourceURL[symbolLink]
109+
package func documentationExtension(for symbolLink: any DocCSymbolLink) -> URL? {
110+
guard let symbolLink = symbolLink as? DocCSymbolLinkImpl else {
111+
return nil
112+
}
113+
return documentationExtensionToSourceURL[symbolLink]
106114
}
107115

108116
init(from renderReferenceStore: RenderReferenceStore) {
@@ -121,7 +129,7 @@ struct DocCCatalogIndex: Sendable {
121129
self.assetReferenceToDataAsset = assetReferenceToDataAsset
122130
self.fuzzyAssetReferenceToDataAsset = fuzzyAssetReferenceToDataAsset
123131
// Markdown and Tutorial content
124-
var documentationExtensionToSourceURL = [DocCSymbolLink: URL]()
132+
var documentationExtensionToSourceURL = [DocCSymbolLinkImpl: URL]()
125133
var articlePathToSourceURLAndReference = [String: (URL, TopicRenderReference)]()
126134
var tutorialPathToSourceURLAndReference = [String: (URL, TopicRenderReference)]()
127135
var tutorialOverviewPathToSourceURLAndReference = [String: (URL, TopicRenderReference)]()
@@ -138,7 +146,7 @@ struct DocCCatalogIndex: Sendable {
138146
else {
139147
continue
140148
}
141-
let doccSymbolLink = DocCSymbolLink(absoluteSymbolLink: absoluteSymbolLink)
149+
let doccSymbolLink = DocCSymbolLinkImpl(absoluteSymbolLink: absoluteSymbolLink)
142150
documentationExtensionToSourceURL[doccSymbolLink] = topicContentValue.source
143151
} else if topicRenderReference.kind == .article {
144152
articlePathToSourceURLAndReference[renderReferenceKey.url.lastPathComponent] = (
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2024 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
package import Foundation
14+
@preconcurrency package import IndexStoreDB
15+
package import LanguageServerProtocol
16+
package import SemanticIndex
17+
18+
/// An actor that can be used to interface with SwiftDocC
19+
package protocol DocCDocumentationManager: Actor {
20+
func getRenderingSupport() -> DocCDocumentationManagerWithRendering?
21+
}
22+
23+
/// An actor that can be used to render SwiftDocC documentation
24+
package protocol DocCDocumentationManagerWithRendering: DocCDocumentationManager {
25+
func filesDidChange(_: [FileEvent]) async
26+
27+
func catalogIndex(for: URL) async throws -> DocCCatalogIndex
28+
29+
func symbolLink(string: String) -> DocCSymbolLink?
30+
31+
func symbolLink(forUSR: String, in: CheckedIndex) -> DocCSymbolLink?
32+
33+
func primaryDefinitionOrDeclarationOccurrence(
34+
ofDocCSymbolLink: DocCSymbolLink,
35+
in: CheckedIndex
36+
) -> SymbolOccurrence?
37+
38+
func renderDocCDocumentation(
39+
symbolUSR: String?,
40+
symbolGraph: String?,
41+
overrideDocComments: [String]?,
42+
markupFile: String?,
43+
tutorialFile: String?,
44+
moduleName: String?,
45+
catalogURL: URL?
46+
) async throws -> DoccDocumentationResponse
47+
}
48+
49+
extension DocCDocumentationManagerWithRendering {
50+
package func renderDocCDocumentation(
51+
symbolUSR: String? = nil,
52+
symbolGraph: String? = nil,
53+
overrideDocComments: [String]? = nil,
54+
markupFile: String? = nil,
55+
tutorialFile: String? = nil,
56+
moduleName: String?,
57+
catalogURL: URL?
58+
) async throws -> DoccDocumentationResponse {
59+
try await renderDocCDocumentation(
60+
symbolUSR: symbolUSR,
61+
symbolGraph: symbolGraph,
62+
overrideDocComments: overrideDocComments,
63+
markupFile: markupFile,
64+
tutorialFile: tutorialFile,
65+
moduleName: moduleName,
66+
catalogURL: catalogURL
67+
)
68+
}
69+
}
70+
71+
/// Creates a new ``DocCDocumentationManager`` that can be used to interface with SwiftDocC.
72+
///
73+
/// - Returns: An instance of ``DocCDocumentationManager``
74+
package func createDocCDocumentationManager() -> any DocCDocumentationManager {
75+
DocCDocumentationManagerImpl()
76+
}

0 commit comments

Comments
 (0)