Skip to content

Commit 300ee6c

Browse files
authored
Allow clang source module targets to be documented using the plugin (#95)
* Allow clang source module targets to be documented using the plugin With this change you can now treat C/C++ targets through clang in the same way as Swift. They can be included in generated doccarchive and previewed in the same way. Update the uses of SwiftSourceModuleTarget to use the more general SourceModuleTarget. * Merge the patch with the latest swift-docc-plugin changes * Code review feedback - rename swiftSourceModuleTarget to sourceModuleTarget
1 parent af7cb03 commit 300ee6c

File tree

7 files changed

+59
-45
lines changed

7 files changed

+59
-45
lines changed

Plugins/SharedPackagePluginExtensions/ArgumentExtractor+extractSpecifiedTargets.swift

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ import PackagePlugin
1212
enum ArgumentParsingError: LocalizedError, CustomStringConvertible {
1313
case unknownProduct(_ productName: String, compatibleProducts: String)
1414
case unknownTarget(_ targetName: String, compatibleTargets: String)
15-
case productDoesNotContainSwiftSourceModuleTargets(String)
16-
case packageDoesNotContainSwiftSourceModuleTargets
17-
case targetIsNotSwiftSourceModule(String)
15+
case productDoesNotContainSourceModuleTargets(String)
16+
case packageDoesNotContainSourceModuleTargets
17+
case targetIsNotSourceModule(String)
1818
case testTarget(String)
1919

2020
var description: String {
@@ -31,13 +31,13 @@ enum ArgumentParsingError: LocalizedError, CustomStringConvertible {
3131
3232
compatible targets: \(compatibleTargets)
3333
"""
34-
case .productDoesNotContainSwiftSourceModuleTargets(let string):
34+
case .productDoesNotContainSourceModuleTargets(let string):
3535
return "product '\(string)' does not contain any Swift source modules"
36-
case .targetIsNotSwiftSourceModule(let string):
36+
case .targetIsNotSourceModule(let string):
3737
return "target '\(string)' is not a Swift source module"
3838
case .testTarget(let string):
3939
return "target '\(string)' is a test target; only library and executable targets are supported by Swift-DocC"
40-
case .packageDoesNotContainSwiftSourceModuleTargets:
40+
case .packageDoesNotContainSourceModuleTargets:
4141
return "the current package does not contain any compatible Swift source modules"
4242
}
4343
}
@@ -48,11 +48,11 @@ enum ArgumentParsingError: LocalizedError, CustomStringConvertible {
4848
}
4949

5050
extension ArgumentExtractor {
51-
mutating func extractSpecifiedTargets(in package: Package) throws -> [SwiftSourceModuleTarget] {
51+
mutating func extractSpecifiedTargets(in package: Package) throws -> [SourceModuleTarget] {
5252
let specifiedProducts = extractOption(named: "product")
5353
let specifiedTargets = extractOption(named: "target")
5454

55-
let productTargets = try specifiedProducts.flatMap { specifiedProduct -> [SwiftSourceModuleTarget] in
55+
let productTargets = try specifiedProducts.flatMap { specifiedProduct -> [SourceModuleTarget] in
5656
let product = package.allProducts.first { product in
5757
product.name == specifiedProduct
5858
}
@@ -64,21 +64,21 @@ extension ArgumentExtractor {
6464
)
6565
}
6666

67-
let supportedSwiftSourceModuleTargets = product.targets.compactMap { target in
68-
target as? SwiftSourceModuleTarget
67+
let supportedSourceModuleTargets = product.targets.compactMap { target in
68+
target as? SourceModuleTarget
6969
}
70-
.filter { swiftSourceModuleTarget in
71-
return swiftSourceModuleTarget.kind != .test
70+
.filter { sourceModuleTarget in
71+
return sourceModuleTarget.kind != .test
7272
}
7373

74-
guard !supportedSwiftSourceModuleTargets.isEmpty else {
75-
throw ArgumentParsingError.productDoesNotContainSwiftSourceModuleTargets(specifiedProduct)
74+
guard !supportedSourceModuleTargets.isEmpty else {
75+
throw ArgumentParsingError.productDoesNotContainSourceModuleTargets(specifiedProduct)
7676
}
7777

78-
return supportedSwiftSourceModuleTargets
78+
return supportedSourceModuleTargets
7979
}
8080

81-
let targets = try specifiedTargets.map { specifiedTarget -> SwiftSourceModuleTarget in
81+
let targets = try specifiedTargets.map { specifiedTarget -> SourceModuleTarget in
8282
let target = package.allTargets.first { target in
8383
target.name == specifiedTarget
8484
}
@@ -90,15 +90,15 @@ extension ArgumentExtractor {
9090
)
9191
}
9292

93-
guard let swiftSourceModuleTarget = target as? SwiftSourceModuleTarget else {
94-
throw ArgumentParsingError.targetIsNotSwiftSourceModule(specifiedTarget)
93+
guard let sourceModuleTarget = target as? SourceModuleTarget else {
94+
throw ArgumentParsingError.targetIsNotSourceModule(specifiedTarget)
9595
}
9696

97-
guard swiftSourceModuleTarget.kind != .test else {
97+
guard sourceModuleTarget.kind != .test else {
9898
throw ArgumentParsingError.testTarget(specifiedTarget)
9999
}
100100

101-
return swiftSourceModuleTarget
101+
return sourceModuleTarget
102102
}
103103

104104
return productTargets + targets

Plugins/SharedPackagePluginExtensions/PackageExtensions.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ extension Package {
6868

6969
/// All targets defined in this package and its dependencies that
7070
/// can produce documentation.
71-
var allDocumentableTargets: [SwiftSourceModuleTarget] {
71+
var allDocumentableTargets: [SourceModuleTarget] {
7272
return allTargets.documentableTargets
7373
}
7474

@@ -83,7 +83,7 @@ extension Package {
8383
/// All targets defined directly in this package that produce documentation.
8484
///
8585
/// Excludes targets defined in dependencies.
86-
var topLevelDocumentableTargets: [SwiftSourceModuleTarget] {
86+
var topLevelDocumentableTargets: [SourceModuleTarget] {
8787
var insertedTargetIds = Set<Target.ID>()
8888
var topLevelTargets = [Target]()
8989

@@ -125,25 +125,25 @@ extension Package {
125125
return allDocumentableProducts.map(\.name.singleQuoted).joined(separator: ", ")
126126
}
127127

128-
func package(for target: SwiftSourceModuleTarget) -> Package? {
128+
func package(for target: SourceModuleTarget) -> Package? {
129129
let possiblePackages = dependencies.map(\.package) + [self]
130130

131131
return possiblePackages.first { package in
132132
package.containsTarget(target)
133133
}
134134
}
135135

136-
func containsTarget(_ target: SwiftSourceModuleTarget) -> Bool {
136+
func containsTarget(_ target: SourceModuleTarget) -> Bool {
137137
return targets.contains { packageTarget in
138138
packageTarget.id == target.id
139139
}
140140
}
141141
}
142142

143143
private extension Collection where Element == Target {
144-
var documentableTargets: [SwiftSourceModuleTarget] {
144+
var documentableTargets: [SourceModuleTarget] {
145145
return compactMap { target in
146-
guard let swiftSourceModuleTarget = target as? SwiftSourceModuleTarget else {
146+
guard let swiftSourceModuleTarget = target as? SourceModuleTarget else {
147147
return nil
148148
}
149149

Plugins/SharedPackagePluginExtensions/PackageManager+getSymbolGraphsForDocC.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ extension PackageManager {
3939

4040
/// Returns the relevant symbols graphs for Swift-DocC documentation generation for the given target.
4141
func doccSymbolGraphs(
42-
for target: SwiftSourceModuleTarget,
42+
for target: SourceModuleTarget,
4343
context: PluginContext,
4444
verbose: Bool,
4545
snippetExtractor: SnippetExtractor?,

Plugins/SharedPackagePluginExtensions/SnippetExtractor+generateSnippetsForTarget.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import PackagePlugin
1111

1212
extension SnippetExtractor {
1313
func generateSnippets(
14-
for target: SwiftSourceModuleTarget,
14+
for target: SourceModuleTarget,
1515
context: PluginContext
1616
) throws -> URL? {
1717
guard let package = context.package.package(for: target) else {

Plugins/SharedPackagePluginExtensions/Target+defaultSymbolGraphOptions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import PackagePlugin
1010

11-
extension SwiftSourceModuleTarget {
11+
extension SourceModuleTarget {
1212
/// Returns the default options that should be used for generating a symbol graph for the
1313
/// current target in the given package.
1414
func defaultSymbolGraphOptions(in package: Package) -> PackageManager.SymbolGraphOptions {

Plugins/Swift-DocC Convert/SwiftDocCConvert.swift

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@ import PackagePlugin
1818
var argumentExtractor = ArgumentExtractor(arguments)
1919
let specifiedTargets = try argumentExtractor.extractSpecifiedTargets(in: context.package)
2020

21-
let swiftSourceModuleTargets: [SwiftSourceModuleTarget]
21+
let sourceModuleTargets: [SourceModuleTarget]
2222
if specifiedTargets.isEmpty {
23-
swiftSourceModuleTargets = context.package.allDocumentableTargets
23+
sourceModuleTargets = context.package.allDocumentableTargets
2424
} else {
25-
swiftSourceModuleTargets = specifiedTargets
25+
sourceModuleTargets = specifiedTargets
2626
}
2727

28-
guard !swiftSourceModuleTargets.isEmpty else {
29-
throw ArgumentParsingError.packageDoesNotContainSwiftSourceModuleTargets
28+
guard !sourceModuleTargets.isEmpty else {
29+
throw ArgumentParsingError.packageDoesNotContainSourceModuleTargets
3030
}
3131

3232
// Parse the given command-line arguments
@@ -66,13 +66,13 @@ import PackagePlugin
6666
try? FileManager.default.createDirectory(at: intermediateArchivesDirectory, withIntermediateDirectories: true)
6767

6868
// An inner function that defines the work to build documentation for a given target.
69-
func performBuildTask(_ task: DocumentationBuildGraph<SwiftSourceModuleTarget>.Task) throws -> URL? {
69+
func performBuildTask(_ task: DocumentationBuildGraph<SourceModuleDocumentationBuildGraphTarget>.Task) throws -> URL? {
7070
let target = task.target
7171
print("Extracting symbol information for '\(target.name)'...")
7272
let symbolGraphGenerationStartTime = DispatchTime.now()
7373

7474
let symbolGraphs = try packageManager.doccSymbolGraphs(
75-
for: target,
75+
for: target.sourceTarget,
7676
context: context,
7777
verbose: verbose,
7878
snippetExtractor: snippetExtractor,
@@ -88,7 +88,7 @@ import PackagePlugin
8888
DocC catalog and will not produce documentation
8989
"""
9090

91-
if swiftSourceModuleTargets.count > 1 {
91+
if sourceModuleTargets.count > 1 {
9292
// We're building multiple targets, just emit a warning for this
9393
// one target that does not produce documentation.
9494
Diagnostics.warning(message)
@@ -107,8 +107,8 @@ import PackagePlugin
107107
intermediateArchivesDirectory.appendingPathComponent("\(target.name).doccarchive", isDirectory: true).path
108108
}
109109

110-
let archiveOutputPath = archiveOutputDir(for: target)
111-
let dependencyArchivePaths: [String] = isCombinedDocumentationEnabled ? task.dependencies.map { archiveOutputDir(for: $0.target) } : []
110+
let archiveOutputPath = archiveOutputDir(for: target.sourceTarget)
111+
let dependencyArchivePaths: [String] = isCombinedDocumentationEnabled ? task.dependencies.map { archiveOutputDir(for: $0.target.sourceTarget) } : []
112112

113113
if verbose {
114114
print("documentation archive output path: '\(archiveOutputPath)'")
@@ -120,7 +120,7 @@ import PackagePlugin
120120
// provided.
121121
let doccArguments = parsedArguments.doccArguments(
122122
action: .convert,
123-
targetKind: target.kind == .executable ? .executable : .library,
123+
targetKind: target.sourceTarget.kind == .executable ? .executable : .library,
124124
doccCatalogPath: target.doccCatalogPath,
125125
targetName: target.name,
126126
symbolGraphDirectoryPath: symbolGraphs.unifiedSymbolGraphsDirectory.path,
@@ -150,7 +150,7 @@ import PackagePlugin
150150
return URL(fileURLWithPath: archiveOutputPath)
151151
}
152152

153-
let buildGraphRunner = DocumentationBuildGraphRunner(buildGraph: .init(targets: swiftSourceModuleTargets))
153+
let buildGraphRunner = DocumentationBuildGraphRunner(buildGraph: .init(targets: sourceModuleTargets.map( {SourceModuleDocumentationBuildGraphTarget(sourceTarget: $0)})))
154154
let intermediateDocumentationArchives = try buildGraphRunner.perform(performBuildTask)
155155
.compactMap { $0 }
156156

@@ -232,18 +232,32 @@ import PackagePlugin
232232
}
233233
}
234234

235-
// We add the conformance here so that 'DocumentationBuildGraphTarget' doesn't need to know about 'SwiftSourceModuleTarget' or import 'PackagePlugin'.
236-
extension SwiftSourceModuleTarget: DocumentationBuildGraphTarget {
235+
// We add the conformance here so that 'DocumentationBuildGraphTarget' doesn't need to know about 'SourceModuleTarget' or import 'PackagePlugin'.
236+
struct SourceModuleDocumentationBuildGraphTarget: DocumentationBuildGraphTarget {
237+
var sourceTarget: SourceModuleTarget
238+
237239
var dependencyIDs: [String] {
238240
// List all the target dependencies in a flat list.
239-
dependencies.flatMap {
241+
sourceTarget.dependencies.flatMap {
240242
switch $0 {
241243
case .target(let target): return [target.id]
242244
case .product(let product): return product.targets.map { $0.id }
243245
@unknown default: return []
244246
}
245247
}
246248
}
249+
250+
var id: String {
251+
sourceTarget.id
252+
}
253+
254+
var name: String {
255+
sourceTarget.name
256+
}
257+
258+
var doccCatalogPath: String? {
259+
sourceTarget.doccCatalogPath
260+
}
247261
}
248262

249263
private extension String {

Plugins/Swift-DocC Preview/SwiftDocCPreview.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import PackagePlugin
2121
var argumentExtractor = ArgumentExtractor(arguments)
2222
let specifiedTargets = try argumentExtractor.extractSpecifiedTargets(in: context.package)
2323

24-
let possibleTargets: [SwiftSourceModuleTarget]
24+
let possibleTargets: [SourceModuleTarget]
2525
if specifiedTargets.isEmpty {
2626
possibleTargets = context.package.topLevelDocumentableTargets
2727
} else {

0 commit comments

Comments
 (0)