Skip to content

Commit 444b7e7

Browse files
authored
Generate test symbol graph with all overload kinds instead of using fixed files (#819)
* Generate symbol graph with all overload kinds instead of fixed files * Check overloadable kind on value instead of on string
1 parent 95a45d0 commit 444b7e7

File tree

5 files changed

+95
-2703
lines changed

5 files changed

+95
-2703
lines changed
Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
This source file is part of the Swift.org open source project
33

4-
Copyright (c) 2023 Apple Inc. and the Swift project authors
4+
Copyright (c) 2023-2024 Apple Inc. and the Swift project authors
55
Licensed under Apache License v2.0 with Runtime Library Exception
66

77
See https://swift.org/LICENSE.txt for license information
@@ -11,20 +11,20 @@
1111
import SymbolKit
1212

1313
extension SymbolGraph.Symbol.KindIdentifier {
14-
/// The kinds of symbols whose documentation pages should be grouped as overloads.
15-
static let overloadableKinds: Set<SymbolGraph.Symbol.KindIdentifier> = [
16-
.method,
17-
.typeMethod,
18-
.`func`,
19-
.`init`,
20-
.macro,
21-
.subscript,
22-
.`operator`
23-
]
24-
25-
/// Whether a string representing a symbol kind matches an overloadable symbol kind.
26-
static func isOverloadableKind(_ kind: String) -> Bool {
27-
return overloadableKinds.contains { $0.identifier == kind }
14+
/// Whether the kind supports grouping as overloads.
15+
var isOverloadableKind: Bool {
16+
switch self {
17+
case .method,
18+
.typeMethod,
19+
.`func`,
20+
.`init`,
21+
.macro,
22+
.subscript,
23+
.`operator`:
24+
return true
25+
default:
26+
return false
27+
}
2828
}
2929
}
3030

Sources/SwiftDocC/Infrastructure/Link Resolution/PathHierarchy.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ extension PathHierarchy {
475475
func traverseOverloadedSymbolGroups(observe: (_ overloadedSymbols: [ResolvedIdentifier]) throws -> Void) rethrows {
476476
for node in lookup.values where node.symbol != nil {
477477
for disambiguation in node.children.values {
478-
for (kind, innerStorage) in disambiguation.storage where innerStorage.count > 1 && SymbolGraph.Symbol.KindIdentifier.isOverloadableKind(kind) {
478+
for (kind, innerStorage) in disambiguation.storage where innerStorage.count > 1 && SymbolGraph.Symbol.KindIdentifier(identifier: kind).isOverloadableKind {
479479
assert(innerStorage.values.allSatisfy { $0.symbol != nil }, "Only symbols should have symbol kind identifiers (\(kind))")
480480

481481
try observe(innerStorage.values.map(\.identifier))

Tests/SwiftDocCTests/Infrastructure/DocumentationContext/DocumentationContextTests.swift

Lines changed: 79 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -4258,101 +4258,107 @@ let expected = """
42584258
}
42594259

42604260
func testContextRecognizesOverloads() throws {
4261+
enableFeatureFlag(\.isExperimentalOverloadedSymbolPresentationEnabled)
4262+
4263+
let overloadableKindIDs = SymbolGraph.Symbol.KindIdentifier.allCases.filter { $0.isOverloadableKind }
4264+
// Generate a 4 symbols with the same name for every overloadable symbol kind
4265+
let symbols: [SymbolGraph.Symbol] = overloadableKindIDs.flatMap { [
4266+
makeSymbol(identifier: "first-\($0.identifier)-id", kind: $0),
4267+
makeSymbol(identifier: "second-\($0.identifier)-id", kind: $0),
4268+
makeSymbol(identifier: "third-\($0.identifier)-id", kind: $0),
4269+
makeSymbol(identifier: "fourth-\($0.identifier)-id", kind: $0),
4270+
] }
4271+
4272+
let tempURL = try createTempFolder(content: [
4273+
Folder(name: "unit-test.docc", content: [
4274+
JSONFile(name: "ModuleName.symbols.json", content: makeSymbolGraph(
4275+
moduleName: "ModuleName",
4276+
symbols: symbols
4277+
))
4278+
])
4279+
])
4280+
let (_, _, context) = try loadBundle(from: tempURL)
42614281

4262-
func checkContainsSiblingOverloads(for overloadedReferences: [ResolvedTopicReference], using context: DocumentationContext, file: StaticString = #file, line: UInt = #line) throws {
4282+
for kindID in overloadableKindIDs {
42634283
var seenIndices = Set<Int>()
4284+
// Find the 4 symbols of this specific kind
4285+
let overloadedReferences = try symbols.filter { $0.kind.identifier == kindID }
4286+
.map { try XCTUnwrap(context.symbolIndex[$0.identifier.precise]) }
42644287

4288+
// Check that each symbol lists the other 3 overloads
42654289
for (index, reference) in overloadedReferences.indexed() {
4266-
let overloadedDocumentationNode = try XCTUnwrap(context.documentationCache[reference], file: file, line: line)
4267-
let overloadedSymbol = try XCTUnwrap(overloadedDocumentationNode.semantic as? Symbol, file: file, line: line)
4268-
4269-
let overloads = try XCTUnwrap(overloadedSymbol.overloadsVariants.firstValue, file: file, line: line)
4270-
4290+
let overloadedDocumentationNode = try XCTUnwrap(context.documentationCache[reference])
4291+
let overloadedSymbol = try XCTUnwrap(overloadedDocumentationNode.semantic as? Symbol)
4292+
4293+
let overloads = try XCTUnwrap(overloadedSymbol.overloadsVariants.firstValue)
4294+
42714295
// Make sure that each symbol contains all of its sibling overloads.
4272-
XCTAssertEqual(overloads.references.count, overloadedReferences.count - 1, file: file, line: line)
4296+
XCTAssertEqual(overloads.references.count, overloadedReferences.count - 1)
42734297
for (otherIndex, otherReference) in overloadedReferences.indexed() where otherIndex != index {
4274-
XCTAssertTrue(overloads.references.contains(otherReference), file: file, line: line)
4298+
XCTAssert(overloads.references.contains(otherReference))
42754299
}
42764300

42774301
// Each symbol needs to tell the renderer where it belongs in the array of overloaded declarations.
4278-
let displayIndex = try XCTUnwrap(overloads.displayIndex, file: file, line: line)
4279-
XCTAssertFalse(seenIndices.contains(displayIndex), file: file, line: line)
4302+
let displayIndex = try XCTUnwrap(overloads.displayIndex)
4303+
XCTAssertFalse(seenIndices.contains(displayIndex))
42804304
seenIndices.insert(displayIndex)
42814305
}
4282-
42834306
// Check that all the overloads was encountered
42844307
for index in overloadedReferences.indices {
4285-
XCTAssert(seenIndices.contains(index), file: file, line: line)
4308+
XCTAssert(seenIndices.contains(index))
42864309
}
42874310
}
4288-
4289-
enableFeatureFlag(\.isExperimentalOverloadedSymbolPresentationEnabled)
4290-
4291-
let (_, _, context) = try testBundleAndContext(copying: "OverloadedSymbols", configureBundle: { url in
4292-
try FileManager.default.copyItem(
4293-
at: Bundle.module.url(forResource: "Animals.symbols", withExtension: "json", subdirectory: "Test Resources")!,
4294-
to: url.appendingPathComponent("Animals.symbols.json"))
4295-
try FileManager.default.copyItem(
4296-
at: Bundle.module.url(forResource: "OverloadedMacros.symbols", withExtension: "json", subdirectory: "Test Resources")!,
4297-
to: url.appendingPathComponent("OverloadedMacros.symbols.json"))
4298-
})
4299-
4300-
let methodsIdentifiers = ["s:7Animals6DragonC3eatyyxlF",
4301-
"s:7Animals6DragonC3eatyySiF",
4302-
"s:7Animals6DragonC3eatyySSF"]
4303-
4304-
let initializerIdentifiers = ["s:7Animals4BirdC5colorACSaySSG_tcfc",
4305-
"s:7Animals4BirdC5colorACSS_tcfc"]
4306-
4307-
let staticMethodIdentifiers = ["s:7Animals4BirdC3flyyySdFZ",
4308-
"s:7Animals4BirdC3flyyySiFZ"]
4309-
4310-
let operatorIdentifiers = ["s:7Animals6DragonC2eeoiySbAC_ACtFZ",
4311-
"s:7Animals6DragonC2eeoiySbAC_yptFZ"]
4312-
4313-
let subscriptIdentifiers = ["s:7Animals4BirdCySSSicip",
4314-
"s:7Animals4BirdCySSs5Int16Vcip"]
4315-
4316-
let functionIdentifiers = ["s:7Animals5sleepyyAA6DragonCF",
4317-
"s:7Animals5sleepyyAA4BirdCF"]
4318-
4319-
let macroIdentifiers = ["s:10testMacros9stringifyyx_SStSSclufm",
4320-
"s:10testMacros9stringifyyx_SStxclufm"]
4321-
4322-
let methodsReferences = try methodsIdentifiers.map { try XCTUnwrap(context.symbolIndex[$0]) }
4323-
let initializerReferences = try initializerIdentifiers.map { try XCTUnwrap(context.symbolIndex[$0]) }
4324-
let staticMethodsReferences = try staticMethodIdentifiers.map { try XCTUnwrap(context.symbolIndex[$0]) }
4325-
let operatorReferences = try operatorIdentifiers.map { try XCTUnwrap(context.symbolIndex[$0]) }
4326-
let subscriptReferences = try subscriptIdentifiers.map { try XCTUnwrap(context.symbolIndex[$0]) }
4327-
let functionReferences = try functionIdentifiers.map { try XCTUnwrap(context.symbolIndex[$0]) }
4328-
let macroReferences = try macroIdentifiers.map { try XCTUnwrap(context.symbolIndex[$0]) }
4329-
4330-
try checkContainsSiblingOverloads(for: methodsReferences, using: context)
4331-
try checkContainsSiblingOverloads(for: initializerReferences, using: context)
4332-
try checkContainsSiblingOverloads(for: staticMethodsReferences, using: context)
4333-
try checkContainsSiblingOverloads(for: operatorReferences, using: context)
4334-
try checkContainsSiblingOverloads(for: subscriptReferences, using: context)
4335-
try checkContainsSiblingOverloads(for: functionReferences, using: context)
4336-
try checkContainsSiblingOverloads(for: macroReferences, using: context)
43374311
}
43384312

4339-
// We do not want to add overload behavior for some symbol kinds, even if they are collisions in the link resolver.
4340-
func testContextDoesNotRecognizeUnoverloadableSymbolKinds() throws {
4313+
// The overload behavior doesn't apply to symbol kinds that don't support overloading
4314+
func testContextDoesNotRecognizeNonOverloadableSymbolKinds() throws {
43414315
enableFeatureFlag(\.isExperimentalOverloadedSymbolPresentationEnabled)
4342-
4343-
let (_, context) = try testBundleAndContext(named: "OverloadedSymbols")
4344-
4345-
let structIdentifiers = ["s:8ShapeKit22overloadedparentstructV",
4346-
"s:8ShapeKit22OverloadedParentStructV"]
43474316

4348-
let structReferences = try structIdentifiers.map { try XCTUnwrap(context.symbolIndex[$0]) }
4317+
let nonOverloadableKindIDs = SymbolGraph.Symbol.KindIdentifier.allCases.filter { !$0.isOverloadableKind }
4318+
// Generate a 4 symbols with the same name for every non overloadable symbol kind
4319+
let symbols: [SymbolGraph.Symbol] = nonOverloadableKindIDs.flatMap { [
4320+
makeSymbol(identifier: "first-\($0.identifier)-id", kind: $0),
4321+
makeSymbol(identifier: "second-\($0.identifier)-id", kind: $0),
4322+
makeSymbol(identifier: "third-\($0.identifier)-id", kind: $0),
4323+
makeSymbol(identifier: "fourth-\($0.identifier)-id", kind: $0),
4324+
] }
43494325

4350-
for reference in structReferences {
4351-
let documentationNode = try XCTUnwrap(context.documentationCache[reference])
4352-
let overloadedSymbol = try XCTUnwrap(documentationNode.semantic as? Symbol)
4353-
XCTAssertNil(overloadedSymbol.overloadsVariants.firstValue)
4326+
let tempURL = try createTempFolder(content: [
4327+
Folder(name: "unit-test.docc", content: [
4328+
JSONFile(name: "ModuleName.symbols.json", content: makeSymbolGraph(
4329+
moduleName: "ModuleName",
4330+
symbols: symbols
4331+
))
4332+
])
4333+
])
4334+
let (_, _, context) = try loadBundle(from: tempURL)
4335+
4336+
for kindID in nonOverloadableKindIDs {
4337+
// Find the 4 symbols of this specific kind
4338+
let overloadedReferences = try symbols.filter { $0.kind.identifier == kindID }
4339+
.map { try XCTUnwrap(context.symbolIndex[$0.identifier.precise]) }
4340+
4341+
// Check that none of the symbols lists any overloads
4342+
for reference in overloadedReferences {
4343+
let documentationNode = try XCTUnwrap(context.documentationCache[reference])
4344+
let overloadedSymbol = try XCTUnwrap(documentationNode.semantic as? Symbol)
4345+
XCTAssertNil(overloadedSymbol.overloadsVariants.firstValue)
4346+
}
43544347
}
43554348
}
4349+
4350+
// A test helper that creates a symbol with a given identifier and kind.
4351+
private func makeSymbol(identifier: String, kind: SymbolGraph.Symbol.KindIdentifier) -> SymbolGraph.Symbol {
4352+
return SymbolGraph.Symbol(
4353+
identifier: .init(precise: identifier, interfaceLanguage: SourceLanguage.swift.id),
4354+
names: .init(title: "SymbolName", navigator: nil, subHeading: nil, prose: nil),
4355+
pathComponents: ["SymbolName"],
4356+
docComment: nil,
4357+
accessLevel: .public,
4358+
kind: .init(parsedIdentifier: kind, displayName: "Kind Display Name"),
4359+
mixins: [:]
4360+
)
4361+
}
43564362
}
43574363

43584364
func assertEqualDumps(_ lhs: String, _ rhs: String, file: StaticString = #file, line: UInt = #line) {

0 commit comments

Comments
 (0)