@@ -5266,7 +5266,165 @@ let expected = """
52665266 }
52675267 }
52685268 }
5269-
5269+
5270+ func testContextDiagnosesInsufficientDisambiguationWithCorrectRange( ) throws {
5271+ // This test deliberately does not turn on the overloads feature
5272+ // to ensure the symbol link below does not accidentally resolve correctly.
5273+ for symbolKindID in SymbolGraph . Symbol. KindIdentifier. allCases where !symbolKindID. isOverloadableKind {
5274+ // Generate a 4 symbols with the same name for every non overloadable symbol kind
5275+ let symbols : [ SymbolGraph . Symbol ] = [
5276+ makeSymbol ( id: " first- \( symbolKindID. identifier) -id " , kind: symbolKindID, pathComponents: [ " SymbolName " ] ) ,
5277+ makeSymbol ( id: " second- \( symbolKindID. identifier) -id " , kind: symbolKindID, pathComponents: [ " SymbolName " ] ) ,
5278+ makeSymbol ( id: " third- \( symbolKindID. identifier) -id " , kind: symbolKindID, pathComponents: [ " SymbolName " ] ) ,
5279+ makeSymbol ( id: " fourth- \( symbolKindID. identifier) -id " , kind: symbolKindID, pathComponents: [ " SymbolName " ] ) ,
5280+ ]
5281+
5282+ let catalog =
5283+ Folder ( name: " unit-test.docc " , content: [
5284+ JSONFile ( name: " ModuleName.symbols.json " , content: makeSymbolGraph (
5285+ moduleName: " ModuleName " ,
5286+ symbols: symbols
5287+ ) ) ,
5288+
5289+ TextFile ( name: " ModuleName.md " , utf8Content: """
5290+ # ``ModuleName``
5291+
5292+ This is a test file for ModuleName.
5293+
5294+ ## Topics
5295+
5296+ - ``SymbolName- \( symbolKindID. identifier) ``
5297+ """ )
5298+ ] )
5299+
5300+ let ( _, context) = try loadBundle ( catalog: catalog)
5301+
5302+ let problems = context. problems. sorted ( by: \. diagnostic. summary)
5303+ XCTAssertEqual ( problems. count, 1 )
5304+
5305+ let problem = try XCTUnwrap ( problems. first)
5306+
5307+ XCTAssertEqual ( problem. diagnostic. summary, " 'SymbolName- \( symbolKindID. identifier) ' is ambiguous at '/ModuleName' " )
5308+
5309+ XCTAssertEqual ( problem. possibleSolutions. count, 4 )
5310+
5311+ for solution in problem. possibleSolutions {
5312+ XCTAssertEqual ( solution. replacements. count, 1 )
5313+ let replacement = try XCTUnwrap ( solution. replacements. first)
5314+
5315+ XCTAssertEqual ( replacement. range. lowerBound, . init( line: 7 , column: 15 , source: nil ) )
5316+ XCTAssertEqual (
5317+ replacement. range. upperBound,
5318+ . init( line: 7 , column: 16 + symbolKindID. identifier. count, source: nil )
5319+ )
5320+ }
5321+ }
5322+ }
5323+
5324+ func testContextDiagnosesIncorrectDisambiguationWithCorrectRange( ) throws {
5325+ // This test deliberately does not turn on the overloads feature
5326+ // to ensure the symbol link below does not accidentally resolve correctly.
5327+ for symbolKindID in SymbolGraph . Symbol. KindIdentifier. allCases where !symbolKindID. isOverloadableKind {
5328+ // Generate a 4 symbols with the same name for every non overloadable symbol kind
5329+ let symbols : [ SymbolGraph . Symbol ] = [
5330+ makeSymbol ( id: " first- \( symbolKindID. identifier) -id " , kind: symbolKindID, pathComponents: [ " SymbolName " ] ) ,
5331+ makeSymbol ( id: " second- \( symbolKindID. identifier) -id " , kind: symbolKindID, pathComponents: [ " SymbolName " ] ) ,
5332+ makeSymbol ( id: " third- \( symbolKindID. identifier) -id " , kind: symbolKindID, pathComponents: [ " SymbolName " ] ) ,
5333+ makeSymbol ( id: " fourth- \( symbolKindID. identifier) -id " , kind: symbolKindID, pathComponents: [ " SymbolName " ] ) ,
5334+ ]
5335+
5336+ let catalog =
5337+ Folder ( name: " unit-test.docc " , content: [
5338+ JSONFile ( name: " ModuleName.symbols.json " , content: makeSymbolGraph (
5339+ moduleName: " ModuleName " ,
5340+ symbols: symbols
5341+ ) ) ,
5342+
5343+ TextFile ( name: " ModuleName.md " , utf8Content: """
5344+ # ``ModuleName``
5345+
5346+ This is a test file for ModuleName.
5347+
5348+ ## Topics
5349+
5350+ - ``SymbolName-abc123``
5351+ """ )
5352+ ] )
5353+
5354+ let ( _, context) = try loadBundle ( catalog: catalog)
5355+
5356+ let problems = context. problems. sorted ( by: \. diagnostic. summary)
5357+ XCTAssertEqual ( problems. count, 1 )
5358+
5359+ let problem = try XCTUnwrap ( problems. first)
5360+
5361+ XCTAssertEqual ( problem. diagnostic. summary, " 'abc123' isn't a disambiguation for 'SymbolName' at '/ModuleName' " )
5362+
5363+ XCTAssertEqual ( problem. possibleSolutions. count, 4 )
5364+
5365+ for solution in problem. possibleSolutions {
5366+ XCTAssertEqual ( solution. replacements. count, 1 )
5367+ let replacement = try XCTUnwrap ( solution. replacements. first)
5368+
5369+ // "Replace '-abc123' with '-(hash)'" where 'abc123' is at 7:15-7:22
5370+ XCTAssertEqual ( replacement. range. lowerBound, . init( line: 7 , column: 15 , source: nil ) )
5371+ XCTAssertEqual ( replacement. range. upperBound, . init( line: 7 , column: 22 , source: nil ) )
5372+ }
5373+ }
5374+ }
5375+
5376+ func testContextDiagnosesIncorrectSymbolNameWithCorrectRange( ) throws {
5377+ // This test deliberately does not turn on the overloads feature
5378+ // to ensure the symbol link below does not accidentally resolve correctly.
5379+ for symbolKindID in SymbolGraph . Symbol. KindIdentifier. allCases where !symbolKindID. isOverloadableKind {
5380+ // Generate a 4 symbols with the same name for every non overloadable symbol kind
5381+ let symbols : [ SymbolGraph . Symbol ] = [
5382+ makeSymbol ( id: " first- \( symbolKindID. identifier) -id " , kind: symbolKindID, pathComponents: [ " SymbolName " ] ) ,
5383+ makeSymbol ( id: " second- \( symbolKindID. identifier) -id " , kind: symbolKindID, pathComponents: [ " SymbolName " ] ) ,
5384+ makeSymbol ( id: " third- \( symbolKindID. identifier) -id " , kind: symbolKindID, pathComponents: [ " SymbolName " ] ) ,
5385+ makeSymbol ( id: " fourth- \( symbolKindID. identifier) -id " , kind: symbolKindID, pathComponents: [ " SymbolName " ] ) ,
5386+ ]
5387+
5388+ let catalog =
5389+ Folder ( name: " unit-test.docc " , content: [
5390+ JSONFile ( name: " ModuleName.symbols.json " , content: makeSymbolGraph (
5391+ moduleName: " ModuleName " ,
5392+ symbols: symbols
5393+ ) ) ,
5394+
5395+ TextFile ( name: " ModuleName.md " , utf8Content: """
5396+ # ``ModuleName``
5397+
5398+ This is a test file for ModuleName.
5399+
5400+ ## Topics
5401+
5402+ - ``Symbol``
5403+ """ )
5404+ ] )
5405+
5406+ let ( _, context) = try loadBundle ( catalog: catalog)
5407+
5408+ let problems = context. problems. sorted ( by: \. diagnostic. summary)
5409+ XCTAssertEqual ( problems. count, 1 )
5410+
5411+ let problem = try XCTUnwrap ( problems. first)
5412+
5413+ XCTAssertEqual ( problem. diagnostic. summary, " 'Symbol' doesn't exist at '/ModuleName' " )
5414+
5415+ XCTAssertEqual ( problem. possibleSolutions. count, 1 )
5416+ let solution = try XCTUnwrap ( problem. possibleSolutions. first)
5417+
5418+ XCTAssertEqual ( solution. summary, " Replace 'Symbol' with 'SymbolName' " )
5419+
5420+ XCTAssertEqual ( solution. replacements. count, 1 )
5421+ let replacement = try XCTUnwrap ( solution. replacements. first)
5422+
5423+ XCTAssertEqual ( replacement. range. lowerBound, . init( line: 7 , column: 5 , source: nil ) )
5424+ XCTAssertEqual ( replacement. range. upperBound, . init( line: 7 , column: 11 , source: nil ) )
5425+ }
5426+ }
5427+
52705428 func testResolveExternalLinkFromTechnologyRoot( ) throws {
52715429 enableFeatureFlag ( \. isExperimentalLinkHierarchySerializationEnabled)
52725430
0 commit comments