diff --git a/Package.resolved b/Package.resolved index ffb8d1e20..111369de6 100644 --- a/Package.resolved +++ b/Package.resolved @@ -3,7 +3,7 @@ { "identity" : "swift-argument-parser", "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-argument-parser.git", + "location" : "https://github.com/apple/swift-argument-parser", "state" : { "revision" : "0fbc8848e389af3bb55c182bc19ca9d5dc2f255b", "version" : "1.4.0" @@ -66,10 +66,10 @@ { "identity" : "swift-docc-symbolkit", "kind" : "remoteSourceControl", - "location" : "https://github.com/swiftlang/swift-docc-symbolkit.git", + "location" : "https://github.com/QuietMisdreavus/swift-docc-symbolkit.git", "state" : { - "branch" : "main", - "revision" : "96bce1cfad4f4d7e265c1eb46729ebf8a7695f4b" + "branch" : "same-shape", + "revision" : "ca7571fd81e6427a8b16a50b162212aee972669a" } }, { diff --git a/Package.swift b/Package.swift index 2381b5dfe..9681b7838 100644 --- a/Package.swift +++ b/Package.swift @@ -137,7 +137,8 @@ if ProcessInfo.processInfo.environment["SWIFTCI_USE_LOCAL_DEPS"] == nil { .package(url: "https://github.com/swiftlang/swift-markdown.git", branch: "main"), .package(url: "https://github.com/swiftlang/swift-lmdb.git", branch: "main"), .package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.2.2"), - .package(url: "https://github.com/swiftlang/swift-docc-symbolkit.git", branch: "main"), +// .package(url: "https://github.com/swiftlang/swift-docc-symbolkit.git", branch: "main"), + .package(url: "https://github.com/QuietMisdreavus/swift-docc-symbolkit.git", branch: "same-shape"), .package(url: "https://github.com/apple/swift-crypto.git", from: "3.0.0"), .package(url: "https://github.com/swiftlang/swift-docc-plugin.git", from: "1.2.0"), ] diff --git a/Sources/SwiftDocC/Model/Rendering/Symbol/ConformanceSection.swift b/Sources/SwiftDocC/Model/Rendering/Symbol/ConformanceSection.swift index 7048c13d3..73ca49b21 100644 --- a/Sources/SwiftDocC/Model/Rendering/Symbol/ConformanceSection.swift +++ b/Sources/SwiftDocC/Model/Rendering/Symbol/ConformanceSection.swift @@ -20,6 +20,7 @@ extension Constraint.Kind { case .conformance: return "conforms to" case .sameType: return "is" case .superclass: return "inherits" + case .sameShape: return "is the same shape as" } } } diff --git a/Tests/SwiftDocCTests/Rendering/ConstraintsRenderSectionTests.swift b/Tests/SwiftDocCTests/Rendering/ConstraintsRenderSectionTests.swift index cf83b6b49..569e0b21e 100644 --- a/Tests/SwiftDocCTests/Rendering/ConstraintsRenderSectionTests.swift +++ b/Tests/SwiftDocCTests/Rendering/ConstraintsRenderSectionTests.swift @@ -11,6 +11,7 @@ import Foundation import XCTest @testable import SwiftDocC +import SwiftDocCTestUtilities import SymbolKit fileprivate let jsonDecoder = JSONDecoder() @@ -273,6 +274,39 @@ class ConstraintsRenderSectionTests: XCTestCase { // Verify we've removed the "Self." prefix in the type names XCTAssertEqual(renderReference.conformance?.constraints.map(flattenInlineElements).joined(), "Element conforms to MyProtocol and Index conforms to Equatable.") } + + func testRenderSameShape() async throws { + let symbolGraphFile = Bundle.module.url( + forResource: "SameShapeConstraint", + withExtension: "symbols.json", + subdirectory: "Test Resources" + )! + + let catalog = Folder(name: "unit-test.docc", content: [ + InfoPlist(displayName: "SameShapeConstraint", identifier: "com.test.example"), + CopyOfFile(original: symbolGraphFile), + ]) + + let (bundle, context) = try await loadBundle(catalog: catalog) + + // Compile docs and verify contents + let node = try context.entity(with: ResolvedTopicReference(bundleID: bundle.id, path: "/documentation/SameShapeConstraint/function(_:)", sourceLanguage: .swift)) + let symbol = node.semantic as! Symbol + var translator = RenderNodeTranslator(context: context, bundle: bundle, identifier: node.reference) + let renderNode = translator.visitSymbol(symbol) as! RenderNode + + guard let renderReference = renderNode.references.first(where: { (key, value) -> Bool in + return key.hasSuffix("function(_:)") + })?.value as? TopicRenderReference else { + XCTFail("Did not find render reference to function(_:)") + return + } + + // The symbol graph only defines constraints on the `swiftGenerics` mixin, + // which docc doesn't load or render. + // However, this test should still run without crashing on decoding the symbol graph. + XCTAssertEqual(renderReference.conformance?.constraints.map(flattenInlineElements).joined(), nil) + } } fileprivate func flattenInlineElements(el: RenderInlineContent) -> String { diff --git a/Tests/SwiftDocCTests/Test Resources/SameShapeConstraint.symbols.json b/Tests/SwiftDocCTests/Test Resources/SameShapeConstraint.symbols.json new file mode 100644 index 000000000..183b29cd2 --- /dev/null +++ b/Tests/SwiftDocCTests/Test Resources/SameShapeConstraint.symbols.json @@ -0,0 +1,321 @@ +{ + "metadata": { + "formatVersion": { + "major": 0, + "minor": 6, + "patch": 0 + }, + "generator": "Apple Swift version 6.2 (swiftlang-6.2.0.19.9 clang-1700.3.19.1)" + }, + "module": { + "name": "SameShapeConstraint", + "platform": { + "architecture": "arm64", + "vendor": "apple", + "operatingSystem": { + "name": "macosx", + "minimumVersion": { + "major": 12, + "minor": 4 + } + } + } + }, + "symbols": [ + { + "kind": { + "identifier": "swift.func", + "displayName": "Function" + }, + "identifier": { + "precise": "s:13SameShapeConstraint8functionyyx_q_txQp_t_tRvzRv_q_Rhzr0_lF", + "interfaceLanguage": "swift" + }, + "pathComponents": [ + "function(_:)" + ], + "names": { + "title": "function(_:)", + "subHeading": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "function" + }, + { + "kind": "text", + "spelling": "((" + }, + { + "kind": "keyword", + "spelling": "repeat" + }, + { + "kind": "text", + "spelling": " (" + }, + { + "kind": "keyword", + "spelling": "each" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "typeIdentifier", + "spelling": "Element0", + "preciseIdentifier": "s:13SameShapeConstraint8functionyyx_q_txQp_t_tRvzRv_q_Rhzr0_lF8Element0L_xmfp" + }, + { + "kind": "text", + "spelling": ", " + }, + { + "kind": "keyword", + "spelling": "each" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "typeIdentifier", + "spelling": "Element1", + "preciseIdentifier": "s:13SameShapeConstraint8functionyyx_q_txQp_t_tRvzRv_q_Rhzr0_lF8Element1L_q_mfp" + }, + { + "kind": "text", + "spelling": ")))" + } + ] + }, + "functionSignature": { + "parameters": [ + { + "name": "_", + "declarationFragments": [ + { + "kind": "identifier", + "spelling": "_" + }, + { + "kind": "text", + "spelling": ": (" + }, + { + "kind": "keyword", + "spelling": "repeat" + }, + { + "kind": "text", + "spelling": " (" + }, + { + "kind": "keyword", + "spelling": "each" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "typeIdentifier", + "spelling": "Element0", + "preciseIdentifier": "s:13SameShapeConstraint8functionyyx_q_txQp_t_tRvzRv_q_Rhzr0_lF8Element0L_xmfp" + }, + { + "kind": "text", + "spelling": ", " + }, + { + "kind": "keyword", + "spelling": "each" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "typeIdentifier", + "spelling": "Element1", + "preciseIdentifier": "s:13SameShapeConstraint8functionyyx_q_txQp_t_tRvzRv_q_Rhzr0_lF8Element1L_q_mfp" + }, + { + "kind": "text", + "spelling": "))" + } + ] + } + ], + "returns": [ + { + "kind": "text", + "spelling": "()" + } + ] + }, + "swiftGenerics": { + "parameters": [ + { + "name": "Element0", + "index": 0, + "depth": 0 + }, + { + "name": "Element1", + "index": 1, + "depth": 0 + } + ], + "constraints": [ + { + "kind": "sameShape", + "lhs": "each Element0", + "rhs": "each Element1" + } + ] + }, + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "function" + }, + { + "kind": "text", + "spelling": "(" + }, + { + "kind": "externalParam", + "spelling": "_" + }, + { + "kind": "text", + "spelling": ": (" + }, + { + "kind": "keyword", + "spelling": "repeat" + }, + { + "kind": "text", + "spelling": " (" + }, + { + "kind": "keyword", + "spelling": "each" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "typeIdentifier", + "spelling": "Element0", + "preciseIdentifier": "s:13SameShapeConstraint8functionyyx_q_txQp_t_tRvzRv_q_Rhzr0_lF8Element0L_xmfp" + }, + { + "kind": "text", + "spelling": ", " + }, + { + "kind": "keyword", + "spelling": "each" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "typeIdentifier", + "spelling": "Element1", + "preciseIdentifier": "s:13SameShapeConstraint8functionyyx_q_txQp_t_tRvzRv_q_Rhzr0_lF8Element1L_q_mfp" + }, + { + "kind": "text", + "spelling": "))) " + }, + { + "kind": "keyword", + "spelling": "where" + }, + { + "kind": "text", + "spelling": " (repeat (each " + }, + { + "kind": "typeIdentifier", + "spelling": "Element0" + }, + { + "kind": "text", + "spelling": ", each " + }, + { + "kind": "typeIdentifier", + "spelling": "Element1" + }, + { + "kind": "text", + "spelling": ")) : Any" + } + ], + "accessLevel": "public", + "location": { + "uri": "file:///path/to/SameShapeConstraint/SwiftClass.swift", + "position": { + "line": 9, + "character": 12 + } + } + } + ], + "relationships": [] +}