mirror of
https://github.com/apple/swift.git
synced 2026-10-02 10:58:03 +02:00
rdar://172117819 (Fix link and parameter documentation errors in Swift stdlib source) While working on #88061, I found about 300 DocC errors in the stdlib source doc comments, which show up as warnings when building the docs with `docc`, and results in incomplete documentation. The problems generally fall into a few common groups: * **Incorrect parameter name**: These occur when a DocC `- Parameter:` tag uses a name different from what's in the signature (for example, using `lhs` and `rhs` to document an `=(_:_:)` operator that actually names its parameters `a` and `b`), or it uses the outer name rather than the inner name. * **Out-of-module links**: DocC can only create links within a symbol's module. The standard library is actually a collection of several modules, with most of what we think of as the stdlib in `core`, but there's also important stuff in `concurrency`, `observation`, etc. And the within-own-module rule means that, for example, docs on `Actor` can't create double-backtick links to `Hashable`, because that's attempting to link from `concurrency` to `core`. I've generally just demoted these to code-voice. * **Link disambiguation**: If a given symbol has many overloads, DocC uses a [disambiguation syntax](https://www.swift.org/documentation/docc/linking-to-symbols-and-other-content#Ambiguous-Symbol-Links) to distinguish between versions with different parameter types, generic conformances, etc. In cases where there was a clear intent to link to a specific version, I added the most appropriate disambiguation link. In other cases, particularly where a doc might be speaking generally to any relevant flavor of a `doFoo()` method, I demoted the link to code voice, since there isn't a "right" disambiguation to choose in these cases. * **Parameters to closures**: DocC has no syntax for cases where a closure parameter itself takes one or more parameters. Generally, the safest approach is to describe these parameters in the documentation of the closure parameter, and this is the only option when the parameter isn't named. In cases where the parameter is named (like `buffer` in the trailing closure for several flavors of `withMemoryRebound()`), @d-ronnqvist suggested using the DocC term list syntax to give the secondary parameter a slight indentation, which is probably what the original author would have wanted. I'm adding the following people as reviewers just so they're aware I'm stomping around in their code: * @ktoso (distributed, runtimemodule) * @phausler (observation) * @al45tair and @carlpeto (runtimemodule - Carl may have just done the DocC formatting) * @Azoy (atomics, ref) * @jmschonfeld (range) * @natecook1000 (range) * @airspeedswift (set) * @glessard (rawspan) * @milseman (string.index) This PR only changes comments, not declarations or code.
129 lines
5.0 KiB
Swift
129 lines
5.0 KiB
Swift
//===--- Mangling.swift --------------------------------------*- swift -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2023 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Defines functions and types allowing to handle Swift's mangling scheme.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
import Swift
|
|
|
|
#if os(anyAppleOS)
|
|
internal import Darwin
|
|
#elseif os(Windows)
|
|
internal import ucrt
|
|
#elseif canImport(Glibc)
|
|
internal import Glibc
|
|
#elseif canImport(Musl)
|
|
internal import Musl
|
|
#endif
|
|
@_implementationOnly import BacktracingImpl.Runtime
|
|
|
|
// - MARK: Demangling
|
|
|
|
/// Given a mangled Swift symbol, demangle it into a human readable format.
|
|
///
|
|
/// If the provided string is not a valid mangled swift identifier this function will throw.
|
|
/// If mangling succeeds the returned string will contain a demangled human-readable representation of the identifier.
|
|
///
|
|
/// - Parameters:
|
|
/// - mangledName: A mangled Swift symbol.
|
|
/// - Returns: A human readable demangled Swift symbol.
|
|
/// - Throws: When the demangling fails for any reason.
|
|
/// - Warning: The demangled output is lossy is not not guaranteed to be stable across Swift versions.
|
|
/// Future versions of Swift may choose to print more (or less) information in the demangled format.
|
|
@available(SwiftStdlib 6.4, *)
|
|
public func demangle(_ mangledName: String) throws(DemanglingError) -> String {
|
|
var demangledLength: size_t = 0
|
|
|
|
let demangled: UnsafeMutablePointer<CChar>? = _swift_runtime_demangle_allocate(
|
|
mangledName, mangledName.utf8.count,
|
|
&demangledLength,
|
|
/*flags=*/0
|
|
)
|
|
|
|
guard demangledLength > 0 else {
|
|
assert(demangled == nil)
|
|
throw .invalidSymbol
|
|
}
|
|
defer { free(demangled) }
|
|
|
|
return try UnsafeBufferPointer(start: demangled, count: demangledLength)
|
|
.withMemoryRebound(to: UTF8.CodeUnit.self) { (buffer: UnsafeBufferPointer<UTF8.CodeUnit>) throws(DemanglingError) -> String in
|
|
guard let demangledSpan = try? UTF8Span(validating: buffer.span) else {
|
|
throw DemanglingError.invalidSymbol
|
|
}
|
|
return String(copying: demangledSpan)
|
|
}
|
|
}
|
|
|
|
/// Given a mangled Swift symbol, demangle it into a human readable format into the prepared output span.
|
|
///
|
|
/// If the provided bytes are not a valid mangled swift name, the output span will be initialized with zero elements.
|
|
/// If mangling succeeds the output span will contain the resulting demangled string.
|
|
/// A successfully demangled string is _not_ null terminated, and its length is communicated by the `initializedCount`
|
|
/// of the output span.
|
|
///
|
|
/// The demangled output may be _truncated_ if the output span's capacity is insufficient for the
|
|
/// demangled output string! You can detect this situation by inspecting the thrown ``DemanglingError``,
|
|
/// for the ``DemanglingError/truncated(requiredBufferSize:)`` case.
|
|
///
|
|
/// - Parameters:
|
|
/// - mangledName: A mangled Swift symbol.
|
|
/// - output: A pre-allocated span to demangle the Swift symbol into.
|
|
/// - Throws: When the demangling failed entirely, and the output span will not have been written to.
|
|
/// - Warning: The demangled output is lossy is not not guaranteed to be stable across Swift versions.
|
|
/// Future versions of Swift may choose to print more (or less) information in the demangled format.
|
|
@available(SwiftStdlib 6.4, *)
|
|
public func demangle(
|
|
_ mangledName: borrowing UTF8Span,
|
|
into output: inout OutputSpan<UTF8.CodeUnit>
|
|
) throws(DemanglingError) {
|
|
var outputCapacity = output.capacity
|
|
|
|
let requiredBufferSize = output.withUnsafeMutableBufferPointer { outputBufferUInt8, initializedOutputLength in
|
|
outputBufferUInt8.withMemoryRebound(to: Int8.self) { outputBuffer in
|
|
mangledName.span.withUnsafeBytes { mangledNamePtr in
|
|
let requiredBufferSize = _swift_runtime_demangle(
|
|
mangledNamePtr.baseAddress, mangledName.count,
|
|
outputBuffer.baseAddress, &outputCapacity,
|
|
/*flags=*/0)
|
|
|
|
initializedOutputLength = outputCapacity
|
|
return requiredBufferSize
|
|
}
|
|
}
|
|
}
|
|
|
|
guard requiredBufferSize > 0 else {
|
|
throw DemanglingError.invalidSymbol
|
|
}
|
|
|
|
// If the buffer size is still equal to the buffer count, the demangle was
|
|
// successful.
|
|
guard requiredBufferSize <= output.capacity else {
|
|
throw DemanglingError.truncated(requiredBufferSize: requiredBufferSize)
|
|
}
|
|
|
|
return // OK!
|
|
}
|
|
|
|
/// Error thrown to indicate failure to demangle a Swift symbol.
|
|
@available(SwiftStdlib 6.4, *)
|
|
public enum DemanglingError: Error {
|
|
/// Demangling resulted in truncating the result. The payload value is the
|
|
/// number of bytes necessary for a full demangle.
|
|
case truncated(requiredBufferSize: Int)
|
|
|
|
/// The passed Swift mangled symbol was invalid.
|
|
case invalidSymbol
|
|
}
|