@@ -64,6 +64,50 @@ class SymbolGraphRelationshipsBuilderTests: XCTestCase {
64
64
XCTAssertFalse ( ( documentationCache [ " B " ] !. semantic as! Symbol ) . defaultImplementations. implementations. isEmpty)
65
65
}
66
66
67
+ func testMultipleImplementsRelationships( ) async throws {
68
+ let ( bundle, context) = try await testBundleAndContext ( )
69
+ var documentationCache = DocumentationContext . ContentCache < DocumentationNode > ( )
70
+ let engine = DiagnosticEngine ( )
71
+
72
+ let identifierA = SymbolGraph . Symbol. Identifier ( precise: " A " , interfaceLanguage: SourceLanguage . swift. id)
73
+ let identifierB = SymbolGraph . Symbol. Identifier ( precise: " B " , interfaceLanguage: SourceLanguage . swift. id)
74
+ let identifierC = SymbolGraph . Symbol. Identifier ( precise: " C " , interfaceLanguage: SourceLanguage . swift. id)
75
+
76
+ let symbolRefA = ResolvedTopicReference ( bundleID: bundle. id, path: " /documentation/SomeModuleName/A " , sourceLanguage: . swift)
77
+ let symbolRefB = ResolvedTopicReference ( bundleID: bundle. id, path: " /documentation/SomeModuleName/B " , sourceLanguage: . swift)
78
+ let symbolRefC = ResolvedTopicReference ( bundleID: bundle. id, path: " /documentation/SomeModuleName/C " , sourceLanguage: . swift)
79
+ let moduleRef = ResolvedTopicReference ( bundleID: bundle. id, path: " /documentation/SomeModuleName " , sourceLanguage: . swift)
80
+
81
+ let symbolA = SymbolGraph . Symbol ( identifier: identifierA, names: SymbolGraph . Symbol. Names ( title: " A " , navigator: nil , subHeading: nil , prose: nil ) , pathComponents: [ " SomeModuleName " , " A " ] , docComment: nil , accessLevel: . init( rawValue: " public " ) , kind: SymbolGraph . Symbol. Kind ( parsedIdentifier: . func, displayName: " Function " ) , mixins: [ : ] )
82
+ let symbolB = SymbolGraph . Symbol ( identifier: identifierB, names: SymbolGraph . Symbol. Names ( title: " B " , navigator: nil , subHeading: nil , prose: nil ) , pathComponents: [ " SomeModuleName " , " B " ] , docComment: nil , accessLevel: . init( rawValue: " public " ) , kind: SymbolGraph . Symbol. Kind ( parsedIdentifier: . func, displayName: " Function " ) , mixins: [ : ] )
83
+ let symbolC = SymbolGraph . Symbol ( identifier: identifierC, names: SymbolGraph . Symbol. Names ( title: " C " , navigator: nil , subHeading: nil , prose: nil ) , pathComponents: [ " SomeModuleName " , " C " ] , docComment: nil , accessLevel: . init( rawValue: " public " ) , kind: SymbolGraph . Symbol. Kind ( parsedIdentifier: . func, displayName: " Function " ) , mixins: [ : ] )
84
+
85
+ documentationCache. add (
86
+ DocumentationNode ( reference: symbolRefA, symbol: symbolA, platformName: " macOS " , moduleReference: moduleRef, article: nil , engine: engine) ,
87
+ reference: symbolRefA,
88
+ symbolID: " A "
89
+ )
90
+ documentationCache. add (
91
+ DocumentationNode ( reference: symbolRefB, symbol: symbolB, platformName: " macOS " , moduleReference: moduleRef, article: nil , engine: engine) ,
92
+ reference: symbolRefB,
93
+ symbolID: " B "
94
+ )
95
+ documentationCache. add (
96
+ DocumentationNode ( reference: symbolRefC, symbol: symbolC, platformName: " macOS " , moduleReference: moduleRef, article: nil , engine: engine) ,
97
+ reference: symbolRefC,
98
+ symbolID: " C "
99
+ )
100
+ XCTAssert ( engine. problems. isEmpty)
101
+
102
+ let edge1 = SymbolGraph . Relationship ( source: identifierB. precise, target: identifierA. precise, kind: . defaultImplementationOf, targetFallback: nil )
103
+ let edge2 = SymbolGraph . Relationship ( source: identifierC. precise, target: identifierA. precise, kind: . defaultImplementationOf, targetFallback: nil )
104
+
105
+ SymbolGraphRelationshipsBuilder . addImplementationRelationship ( edge: edge1, selector: swiftSelector, in: bundle, context: context, localCache: documentationCache, engine: engine)
106
+ SymbolGraphRelationshipsBuilder . addImplementationRelationship ( edge: edge2, selector: swiftSelector, in: bundle, context: context, localCache: documentationCache, engine: engine)
107
+
108
+ XCTAssertEqual ( ( documentationCache [ " A " ] !. semantic as! Symbol ) . defaultImplementations. groups. first? . references. map ( \. url? . lastPathComponent) , [ " B " , " C " ] )
109
+ }
110
+
67
111
func testConformsRelationship( ) async throws {
68
112
let ( bundle, _) = try await testBundleAndContext ( )
69
113
var documentationCache = DocumentationContext . ContentCache < DocumentationNode > ( )
0 commit comments