@@ -64,6 +64,50 @@ class SymbolGraphRelationshipsBuilderTests: XCTestCase {
6464 XCTAssertFalse ( ( documentationCache [ " B " ] !. semantic as! Symbol ) . defaultImplementations. implementations. isEmpty)
6565 }
6666
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+
67111 func testConformsRelationship( ) async throws {
68112 let ( bundle, _) = try await testBundleAndContext ( )
69113 var documentationCache = DocumentationContext . ContentCache < DocumentationNode > ( )
0 commit comments