Skip to content

Hide parameter and return value documentation from properties. #968

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 27 additions & 8 deletions Sources/SwiftDocC/Model/ParametersAndReturnValidator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -222,12 +222,19 @@ struct ParametersAndReturnValidator {
var variants = DocumentationDataVariants<ReturnsSection>()

var traitsWithNonVoidReturnValues = Set(signatures.keys)
for (trait, signature) in signatures where !signature.returns.isEmpty {
// Don't display any return value documentation for language representations that only return void.
if let language = trait.interfaceLanguage.flatMap(SourceLanguage.init(knownLanguageIdentifier:)),
let voidReturnValues = Self.knownVoidReturnValuesByLanguage[language],
signature.returns.allSatisfy({ voidReturnValues.contains($0) })
{
for (trait, signature) in signatures {
/// A Boolean value that indicates whether the current signature returns a known "void" value.
var returnsKnownVoidValue: Bool {
guard let language = trait.interfaceLanguage.flatMap(SourceLanguage.init(knownLanguageIdentifier:)),
let voidReturnValues = Self.knownVoidReturnValuesByLanguage[language]
else {
return false
}
return signature.returns.allSatisfy { voidReturnValues.contains($0) }
}

// Don't display any return value documentation for language representations that return nothing or that only return void.
if signature.returns.isEmpty || returnsKnownVoidValue {
traitsWithNonVoidReturnValues.remove(trait)
// Add an empty section so that this language doesn't fallback to another language's content.
variants[trait] = ReturnsSection(content: [])
Expand Down Expand Up @@ -273,7 +280,19 @@ struct ParametersAndReturnValidator {
}
signatures[DocumentationDataVariantsTrait(for: selector)] = signature
}
return signatures.isEmpty ? nil : signatures

guard !signatures.isEmpty else { return nil }

// If the unified symbol has at least one function signature, fill in empty signatures for the other language representations.
//
// This, for example, makes it so that a functions in C which corresponds to property in Swift, displays its parameters and return value documentation
// for the C function representation, but not the Swift property representation of the documented symbol.
let traitsWithoutSignatures = Set(symbol.mainGraphSelectors.map { DocumentationDataVariantsTrait(for: $0) }).subtracting(signatures.keys)
for trait in traitsWithoutSignatures {
signatures[trait] = .init(parameters: [], returns: [])
}

return signatures
}

/// Checks if the language specific function signatures describe a throwing function in Swift that bridges to an Objective-C method with a trailing error parameter.
Expand All @@ -285,7 +304,7 @@ struct ParametersAndReturnValidator {
return false
}
guard let swiftSignature = signatures[.swift],
swiftSignature.parameters.last?.name != "error"
swiftSignature.parameters.last?.name != "error"
else {
return false
}
Expand Down
33 changes: 33 additions & 0 deletions Tests/SwiftDocCTests/Model/ParametersAndReturnValidatorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,39 @@ class ParametersAndReturnValidatorTests: XCTestCase {
}
}

func testFunctionsThatCorrespondToPropertiesInAnotherLanguage() throws {
let (_, _, context) = try testBundleAndContext(named: "GeometricalShapes")
XCTAssertEqual(context.problems.map(\.diagnostic.summary), [])

// A small test helper to format markup for test assertions in this test.
func _format(_ markup: [any Markup]) -> String {
markup.map { $0.format() }.joined()
}

let reference = try XCTUnwrap(context.knownPages.first(where: { $0.lastPathComponent == "isEmpty" }))
let node = try context.entity(with: reference)

let symbolSemantic = try XCTUnwrap(node.semantic as? Symbol)
let swiftParameterNames = symbolSemantic.parametersSectionVariants.firstValue?.parameters
let objcParameterNames = symbolSemantic.parametersSectionVariants.allValues.mapFirst(where: { (trait, variant) -> [Parameter]? in
guard trait.interfaceLanguage == SourceLanguage.objectiveC.id else { return nil }
return variant.parameters
})

XCTAssertEqual(swiftParameterNames?.map(\.name), [])
XCTAssertEqual(objcParameterNames?.map(\.name), ["circle"])
XCTAssertEqual(objcParameterNames?.map { _format($0.contents) }, ["The circle to examine."])

let swiftReturnsContent = symbolSemantic.returnsSection.map { _format($0.content) }
let objcReturnsContent = symbolSemantic.returnsSectionVariants.allValues.mapFirst(where: { (trait, variant) -> String? in
guard trait.interfaceLanguage == SourceLanguage.objectiveC.id else { return nil }
return variant.content.map { $0.format() }.joined()
})

XCTAssertEqual(swiftReturnsContent, "")
XCTAssertEqual(objcReturnsContent, "`YES` if the specified circle is empty; otherwise, `NO`.")
}

func testNoParameterDiagnosticWithoutFunctionSignature() throws {
var symbolGraph = makeSymbolGraph(docComment: """
Some function description
Expand Down
Loading