Skip to content

Commit 21c6c47

Browse files
committed
Add docstrings, and minor code cleanup
1 parent bf7f423 commit 21c6c47

File tree

1 file changed

+26
-5
lines changed

1 file changed

+26
-5
lines changed

lib/Macros/Sources/SwiftMacros/DebugDescriptionMacro.swift

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import SwiftDiagnostics
44

55
public struct DebugDescriptionMacro {}
66

7+
/// Attached peer macro which converts `debugDescription` (or `description`) implementations into
8+
/// an LLDB type summary. The type summary record is emitted into a custom section (via a global
9+
/// constant), where LLDB will load from at debug time.
710
extension DebugDescriptionMacro: PeerMacro {
811
public static func expansion<Decl, Context>(
912
of node: AttributeSyntax,
@@ -114,7 +117,7 @@ extension DebugDescriptionMacro: PeerMacro {
114117
@unknown default:
115118
return []
116119
}
117-
}
120+
}
118121

119122
let summaryString = summarySegments.joined()
120123

@@ -152,7 +155,7 @@ extension DebugDescriptionMacro: PeerMacro {
152155

153156
// MARK: - Diagnostics
154157

155-
struct ErrorMessage: DiagnosticMessage, ExpressibleByStringInterpolation {
158+
private struct ErrorMessage: DiagnosticMessage, ExpressibleByStringInterpolation {
156159
init(stringLiteral value: String) {
157160
self.message = value
158161
}
@@ -229,8 +232,8 @@ private func isComputedProperty(_ binding: PatternBindingSyntax) -> Bool {
229232
// Enumerate a MemberAccess expression to produce DeclReferences in left to right order.
230233
// `a.b.c` will result in callbacks for each DeclReference `a`, `b`, and then `c`.
231234
private func enumerateMembers(_ memberAccess: MemberAccessExprSyntax, _ action: (DeclReferenceExprSyntax) -> Void) {
232-
if let baseMembers = memberAccess.base?.as(MemberAccessExprSyntax.self) {
233-
enumerateMembers(baseMembers, action)
235+
if let baseMember = memberAccess.base?.as(MemberAccessExprSyntax.self) {
236+
enumerateMembers(baseMember, action)
234237
} else if let baseDecl = memberAccess.base?.as(DeclReferenceExprSyntax.self) {
235238
action(baseDecl)
236239
}
@@ -239,6 +242,18 @@ private func enumerateMembers(_ memberAccess: MemberAccessExprSyntax, _ action:
239242

240243
// MARK: - Encoding
241244

245+
/// Construct an LLDB type summary record.
246+
///
247+
/// The record is serializeed as a tuple of `UInt8` bytes.
248+
///
249+
/// The record contains the following:
250+
/// * Version number of the record format
251+
/// * The size of the record (encoded as ULEB)
252+
/// * The type identifier, which is either a type name, or for generic types a type regex
253+
/// * The description string converted to an LLDB summary string
254+
///
255+
/// The strings (type identifier and summary) are encoded with both a length prefix (also ULEB)
256+
/// and with a null terminator.
242257
private func encodeTypeSummaryRecord(_ typeIdentifier: String, _ summaryString: String) -> String {
243258
let encodedType = encodeString(typeIdentifier)
244259
let encodedSummary = encodeString(summaryString)
@@ -251,19 +266,23 @@ private func encodeTypeSummaryRecord(_ typeIdentifier: String, _ summaryString:
251266
"""
252267
}
253268

269+
/// Generate a _partial_ Swift literal from the given bytes. It is partial in that must be embedded
270+
/// into some other syntax, specifically as a tuple.
254271
private func literalBytes(_ bytes: [UInt8]) -> String {
255272
bytes.map({ "\($0) as UInt8" }).joined(separator: ", ")
256273
}
257274

275+
/// Encode a string into UTF8 bytes, prefixed by a ULEB length, and suffixed by the null terminator.
258276
private func encodeString(_ string: String) -> [UInt8] {
259277
let size = UInt(string.utf8.count) + 1 // including null terminator
260278
var bytes: [UInt8] = []
261279
bytes.append(contentsOf: encodeULEB(size))
262-
bytes.append(contentsOf: Array(string.utf8))
280+
bytes.append(contentsOf: string.utf8)
263281
bytes.append(0) // null terminator
264282
return bytes
265283
}
266284

285+
/// Encode an unsigned integer into ULEB format. See https://en.wikipedia.org/wiki/LEB128
267286
private func encodeULEB(_ value: UInt) -> [UInt8] {
268287
guard value > 0 else {
269288
return [0]
@@ -285,6 +304,8 @@ private func encodeULEB(_ value: UInt) -> [UInt8] {
285304
// MARK: - Extensions
286305

287306
extension Collection {
307+
/// Convert a single element collection to a single value. When a collection consists of
308+
/// multiple elements, nil is returned.
288309
fileprivate var single: Element? {
289310
count == 1 ? first : nil
290311
}

0 commit comments

Comments
 (0)