Skip to content

Commit 2421110

Browse files
Add DocC generators, CLI, Integration, and build scripts
1 parent ae985dd commit 2421110

File tree

8 files changed

+636
-8
lines changed

8 files changed

+636
-8
lines changed

Package.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ let package = Package(
1717
.executable(
1818
name: "openapi-to-symbolgraph",
1919
targets: ["CLI"]),
20+
.executable(
21+
name: "symbol-graph-debug",
22+
targets: ["SymbolGraphDebug"]),
2023
],
2124
dependencies: [
2225
.package(url: "https://github.com/jpsim/Yams.git", from: "5.0.6"),
@@ -83,6 +86,15 @@ let package = Package(
8386
path: "Sources/CLI",
8487
exclude: ["README.md"]
8588
),
89+
.executableTarget(
90+
name: "SymbolGraphDebug",
91+
dependencies: [
92+
"OpenAPItoSymbolGraph",
93+
.product(name: "ArgumentParser", package: "swift-argument-parser"),
94+
.product(name: "SymbolKit", package: "swift-docc-symbolkit")
95+
],
96+
path: "Sources/SymbolGraphDebug"
97+
),
8698
.testTarget(
8799
name: "OpenAPItoSymbolGraphTests",
88100
dependencies: [

Sources/CLI/main.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ struct OpenAPIToSymbolGraph: ParsableCommand {
2020
@Option(name: .long, help: "Name to use for the module in the symbol graph", transform: { $0 })
2121
var moduleName: String?
2222

23+
@Option(name: .long, help: "Base URL of the API for HTTP endpoint documentation", transform: { URL(string: $0) })
24+
var baseURL: URL?
25+
2326
mutating func run() throws {
2427
// Check file extension
2528
let fileExtension = URL(fileURLWithPath: inputPath).pathExtension.lowercased()
@@ -40,7 +43,7 @@ struct OpenAPIToSymbolGraph: ParsableCommand {
4043
let document = try parser.parse(fileContent)
4144

4245
// Convert to symbol graph
43-
let converter = Integration.OpenAPIDocCConverter(moduleName: moduleName)
46+
let converter = Integration.OpenAPIDocCConverter(moduleName: moduleName, baseURL: baseURL)
4447
let symbolGraph = converter.convert(document)
4548

4649
// Write the symbol graph to file
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import Foundation
2+
import SymbolKit
3+
import OpenAPI
4+
5+
// Custom HTTP mixins implementation that follows SymbolKit pattern
6+
extension SymbolKit.SymbolGraph.Symbol {
7+
/// Namespace for HTTP-specific mixins
8+
public enum HTTP {
9+
/// Mixin key for HTTP endpoint information
10+
public static let endpointMixinKey = "httpEndpoint"
11+
12+
/// Mixin key for HTTP parameter source information
13+
public static let parameterSourceMixinKey = "httpParameterSource"
14+
15+
/// Mixin key for HTTP media type information
16+
public static let mediaTypeMixinKey = "httpMediaType"
17+
18+
/// The HTTP endpoint for a request.
19+
public struct Endpoint: Codable, SymbolKit.Mixin {
20+
public static let mixinKey = endpointMixinKey
21+
22+
/// The HTTP method of the request (e.g., GET, POST, PUT, DELETE).
23+
/// The value is always uppercased.
24+
public var method: String
25+
26+
/// The base URL of the request.
27+
public var baseURL: URL
28+
29+
/// The alternate base URL of the request when used within a test environment.
30+
public var sandboxURL: URL?
31+
32+
/// The relative path specific to the endpoint.
33+
public var path: String
34+
35+
public init(method: String, baseURL: URL, sandboxURL: URL? = nil, path: String) {
36+
self.method = method.uppercased()
37+
self.baseURL = baseURL
38+
self.sandboxURL = sandboxURL
39+
self.path = path
40+
}
41+
}
42+
43+
/// The source location of an HTTP parameter.
44+
public struct ParameterSource: Codable, SymbolKit.Mixin {
45+
public static let mixinKey = parameterSourceMixinKey
46+
47+
/// The parameter source location (path, query, header, or cookie)
48+
public var value: String
49+
50+
public init(_ value: String) {
51+
self.value = value
52+
}
53+
54+
public init(_ location: ParameterLocation) {
55+
self.value = location.rawValue
56+
}
57+
}
58+
59+
/// The encoding media type for an HTTP payload.
60+
public struct MediaType: Codable, SymbolKit.Mixin {
61+
public static let mixinKey = mediaTypeMixinKey
62+
63+
/// The media type (e.g., "application/json")
64+
public var value: String
65+
66+
public init(_ value: String) {
67+
self.value = value
68+
}
69+
}
70+
}
71+
}
72+
73+
/// Protocol for SymbolKit mixins to ensure consistency
74+
public protocol Mixin: Encodable {
75+
/// The key used to identify this mixin in a symbol's mixins dictionary
76+
static var mixinKey: String { get }
77+
}

Sources/DocC/Generators/SymbolGraphGenerator.swift

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,22 @@ import SymbolKit
66
public struct SymbolGraphGenerator {
77
/// The name to use for the module
88
public var moduleName: String?
9+
/// Base URL for the API
10+
public var baseURL: URL?
911

1012
/// Creates a new symbol graph generator
11-
public init(moduleName: String? = nil) {
13+
public init(moduleName: String? = nil, baseURL: URL? = nil) {
1214
self.moduleName = moduleName
15+
self.baseURL = baseURL
1316
}
1417

1518
/// Generates a symbol graph from an OpenAPI document
1619
/// - Parameter document: The OpenAPI document to convert
1720
/// - Returns: The generated symbol graph
1821
public func generate(from document: Document) -> SymbolKit.SymbolGraph {
22+
// For now, we'll skip the mixin registration as it requires more work to implement correctly
23+
// We're still generating valid symbol graphs, just without the HTTP-specific enhancements
24+
1925
var symbols: [SymbolKit.SymbolGraph.Symbol] = []
2026
var relationships: [SymbolKit.SymbolGraph.Relationship] = []
2127

@@ -187,14 +193,27 @@ public struct SymbolGraphGenerator {
187193
docComment = SymbolKit.SymbolGraph.LineList([line])
188194
}
189195

196+
// Create mixins for HTTP endpoint
197+
var mixins: [String: SymbolKit.Mixin] = [:]
198+
199+
// Add HTTP endpoint mixin if baseURL is provided
200+
if let baseURL = self.baseURL {
201+
let httpEndpoint = SymbolKit.SymbolGraph.Symbol.HTTP.Endpoint(
202+
method: method.rawValue,
203+
baseURL: baseURL,
204+
path: path
205+
)
206+
mixins[SymbolKit.SymbolGraph.Symbol.HTTP.endpointMixinKey] = httpEndpoint
207+
}
208+
190209
return SymbolKit.SymbolGraph.Symbol(
191210
identifier: identifier,
192211
names: names,
193212
pathComponents: [path, method.rawValue],
194213
docComment: docComment,
195214
accessLevel: SymbolKit.SymbolGraph.Symbol.AccessControl(rawValue: "public"),
196215
kind: .init(parsedIdentifier: .method, displayName: "Operation"),
197-
mixins: [:]
216+
mixins: mixins
198217
)
199218
}
200219

@@ -218,14 +237,21 @@ public struct SymbolGraphGenerator {
218237
docComment = SymbolKit.SymbolGraph.LineList([line])
219238
}
220239

240+
// Create mixins for HTTP parameter
241+
var mixins: [String: SymbolKit.Mixin] = [:]
242+
243+
// Add HTTP parameter source mixin
244+
let httpParameterSource = SymbolKit.SymbolGraph.Symbol.HTTP.ParameterSource(parameter.in)
245+
mixins[SymbolKit.SymbolGraph.Symbol.HTTP.parameterSourceMixinKey] = httpParameterSource
246+
221247
return SymbolKit.SymbolGraph.Symbol(
222248
identifier: identifier,
223249
names: names,
224250
pathComponents: operation.pathComponents + [parameter.name],
225251
docComment: docComment,
226252
accessLevel: SymbolKit.SymbolGraph.Symbol.AccessControl(rawValue: "public"),
227253
kind: .init(parsedIdentifier: .property, displayName: "Parameter"),
228-
mixins: [:]
254+
mixins: mixins
229255
)
230256
}
231257

@@ -247,14 +273,23 @@ public struct SymbolGraphGenerator {
247273
let line = SymbolKit.SymbolGraph.LineList.Line(text: response.description, range: nil)
248274
let docComment = SymbolKit.SymbolGraph.LineList([line])
249275

276+
// Create mixins for HTTP response
277+
var mixins: [String: SymbolKit.Mixin] = [:]
278+
279+
// Add HTTP media type mixin if content is available
280+
if let content = response.content?.first {
281+
let mediaType = SymbolKit.SymbolGraph.Symbol.HTTP.MediaType(content.key)
282+
mixins[SymbolKit.SymbolGraph.Symbol.HTTP.mediaTypeMixinKey] = mediaType
283+
}
284+
250285
return SymbolKit.SymbolGraph.Symbol(
251286
identifier: identifier,
252287
names: names,
253288
pathComponents: operation.pathComponents + [statusCode],
254289
docComment: docComment,
255290
accessLevel: SymbolKit.SymbolGraph.Symbol.AccessControl(rawValue: "public"),
256291
kind: .init(parsedIdentifier: .struct, displayName: "Response"),
257-
mixins: [:]
292+
mixins: mixins
258293
)
259294
}
260295

Sources/Integration/OpenAPIDocCConverter.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,20 @@ import SymbolKit
77
public struct OpenAPIDocCConverter {
88
/// The name to use for the module
99
private let moduleName: String?
10+
/// Base URL for the API
11+
private let baseURL: URL?
1012

1113
/// Creates a new OpenAPI to DocC converter
12-
public init(moduleName: String? = nil) {
14+
public init(moduleName: String? = nil, baseURL: URL? = nil) {
1315
self.moduleName = moduleName
16+
self.baseURL = baseURL
1417
}
1518

1619
/// Converts an OpenAPI document to a DocC symbol graph
1720
/// - Parameter document: The OpenAPI document to convert
1821
/// - Returns: The DocC symbol graph
1922
public func convert(_ document: Document) -> SymbolKit.SymbolGraph {
20-
let generator = SymbolGraphGenerator(moduleName: moduleName)
23+
let generator = SymbolGraphGenerator(moduleName: moduleName, baseURL: baseURL)
2124
return generator.generate(from: document)
2225
}
2326
}

Sources/SymbolGraphDebug/README.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Symbol Graph Debug Tool
2+
3+
This tool helps debug and analyze DocC symbol graphs generated from OpenAPI specifications. It provides several commands to help you understand the structure of your symbol graphs and identify issues.
4+
5+
## Usage
6+
7+
```
8+
swift run symbol-graph-debug [command] [options]
9+
```
10+
11+
### Commands
12+
13+
- **analyze**: Performs a comprehensive analysis of a symbol graph
14+
- **validate-relationships**: Validates all relationships in a symbol graph
15+
- **show-symbol**: Shows detailed information about a specific symbol
16+
- **show-http**: Shows HTTP-specific information for API endpoints
17+
18+
## Findings
19+
20+
Through our investigation using this tool, we've identified several insights about the OpenAPI integration with DocC:
21+
22+
1. **Symbol Graph Structure**: The OpenAPI to Symbol Graph conversion is generating valid symbol graphs with correct relationships.
23+
24+
2. **HTTP Mixins**: SymbolKit provides HTTP-specific mixins that can enhance API documentation with endpoint details, parameter sources, and media types.
25+
26+
3. **DocC Integration Challenges**:
27+
- DocC doesn't seem to fully render symbols from the OpenAPI interface language
28+
- Child symbols aren't appearing in the `topicSections` array of the module JSON
29+
- This suggests DocC may not be properly associating or recognizing these symbols
30+
31+
4. **Module Name Consistency**: It's critical to ensure the module name is consistent between:
32+
- The symbol graph's `module.name` value
33+
- The DocC documentation target
34+
- Path components in symbols
35+
36+
5. **Relationship Structure**: The relationship structure is valid but might need adjustments to be fully recognized by DocC.
37+
38+
## Potential Solutions
39+
40+
1. **Interface Language**: Consider using "swift" as the interface language instead of "openapi" to potentially improve DocC compatibility.
41+
42+
2. **HTTP Mixins**: Fully implement HTTP mixins to enhance REST API documentation.
43+
44+
3. **Symbol Registration**: Implement proper symbol registration for mixins to enable DocC to recognize and utilize HTTP-specific information.
45+
46+
4. **DocC Extensions**: Consider creating DocC extensions specifically for OpenAPI types to improve rendering.
47+
48+
## Example Usage
49+
50+
```bash
51+
# Analyze a symbol graph
52+
.build/debug/symbol-graph-debug analyze registry.symbolgraph.json
53+
54+
# Validate relationships
55+
.build/debug/symbol-graph-debug validate-relationships registry.symbolgraph.json
56+
57+
# Show HTTP endpoints
58+
.build/debug/symbol-graph-debug show-http registry.symbolgraph.json
59+
60+
# Show details of a specific symbol
61+
.build/debug/symbol-graph-debug show-symbol registry.symbolgraph.json "module"
62+
```

0 commit comments

Comments
 (0)