Skip to content

Commit 7477774

Browse files
macmadeclaude
andcommitted
docs: Document all types and members with SwiftDoc comments
Add SwiftDoc comments to every type and member across the app, editor extension, and shared code, including private and internal declarations, IBOutlets, IBActions, and KVO-observable properties. Existing partial or free-form comments were validated and converted to SwiftDoc, with parameter, return, and throws tags added where relevant. In-body implementation comments are left unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 0ed670f commit 7477774

26 files changed

Lines changed: 588 additions & 0 deletions

EditorExtension/SourceEditorCommand.swift

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,26 @@ import Foundation
2626
import UniformTypeIdentifiers
2727
import XcodeKit
2828

29+
/// The Xcode source editor command that formats the active buffer.
30+
///
31+
/// Invoked from Xcode's *Editor ▸ XcodeFormat* menu, it picks the formatter
32+
/// matching the buffer's type — SwiftFormat for Swift, uncrustify for the C
33+
/// family — using the user's selected configuration, then rewrites the buffer
34+
/// and restores the caret.
2935
public class SourceEditorCommand: NSObject, XCSourceEditorCommand
3036
{
37+
/// Entry point Xcode calls to run the command on the current buffer.
38+
///
39+
/// Resolves the selected configuration and the buffer's uniform type, makes
40+
/// the needed configuration files available locally, and formats the buffer
41+
/// with the matching tool. Does nothing (reporting success) when there is no
42+
/// selected configuration or the buffer's type is unknown.
43+
///
44+
/// - Parameters:
45+
/// - invocation: The buffer and command context provided by Xcode.
46+
/// - completionHandler: Called once formatting finishes; receives an error
47+
/// to surface in Xcode's banner, or `nil` on success
48+
/// or a silent no-op.
3149
public func perform( with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping ( Error? ) -> Void )
3250
{
3351
guard let configuration = Preferences.shared.selectedConfiguration,
@@ -67,6 +85,22 @@ public class SourceEditorCommand: NSObject, XCSourceEditorCommand
6785
}
6886
}
6987

88+
/// Runs a formatter over the buffer's full contents and, if it produced
89+
/// changed output, replaces the buffer and restores the caret.
90+
///
91+
/// The buffer text is piped to the executable as UTF-8 standard input. The
92+
/// result is classified by ``FormatterOutcome``; only a `.formatted`
93+
/// outcome rewrites the buffer. When a single (empty) selection exists, its
94+
/// caret is mapped onto the formatted text via
95+
/// ``CursorPosition/restored(in:line:column:)``.
96+
///
97+
/// - Parameters:
98+
/// - buffer: The source buffer to read from and write back to.
99+
/// - executable: Name of the formatter executable to run.
100+
/// - arguments: Command-line arguments for the formatter.
101+
/// - Throws: ``FormatterError/executableNotFound(_:)`` if the tool could not
102+
/// be launched, or ``FormatterError/failed(executable:status:message:)``
103+
/// if it exited with a non-zero status.
70104
private func format( buffer: XCSourceTextBuffer, executable: String, arguments: [ String ] ) throws
71105
{
72106
guard let data = buffer.completeBuffer.data( using: .utf8 )

EditorExtension/SourceEditorExtension.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,15 @@
2525
import Foundation
2626
import XcodeKit
2727

28+
/// The Xcode source editor extension principal object.
29+
///
30+
/// Xcode instantiates it when the extension is loaded; it warms the local
31+
/// cache by downloading each known configuration so a format command can run
32+
/// without waiting on the network.
2833
class SourceEditorExtension: NSObject, XCSourceEditorExtension
2934
{
35+
/// Called by Xcode once the extension has launched; kicks off a download of
36+
/// every stored configuration to populate the shared cache.
3037
func extensionDidFinishLaunching()
3138
{
3239
Preferences.shared.configurations.forEach

Shared/Configuration.swift

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,31 @@
2525
import CryptoKit
2626
import Foundation
2727

28+
/// A named formatting profile pairing a SwiftFormat configuration URL with an
29+
/// uncrustify configuration URL.
30+
///
31+
/// Configurations are persisted via ``Preferences`` and synced between the
32+
/// main app and the editor extension. Each remote configuration file is
33+
/// downloaded over HTTPS into the shared app-group container, keyed by a hash
34+
/// of its URL and stored alongside a content hash so a tampered or partial
35+
/// cache can be rejected at read time.
2836
@objc
2937
public class Configuration: NSObject, Codable
3038
{
39+
/// User-visible name of the configuration.
3140
@objc public dynamic var name: String
41+
42+
/// URL of the SwiftFormat configuration file, or `nil` if none.
3243
@objc public dynamic var swiftFormat: URL?
44+
45+
/// URL of the uncrustify configuration file, or `nil` if none.
3346
@objc public dynamic var uncrustify: URL?
47+
48+
/// Whether a download of this configuration's files is in progress.
49+
/// KVO-observable so UI can show progress.
3450
@objc public dynamic var downloading = false
3551

52+
/// The built-in configurations seeded on first launch.
3653
public static var defaultConfigurations: [ Configuration ]
3754
{
3855
[
@@ -43,6 +60,13 @@ public class Configuration: NSObject, Codable
4360
]
4461
}
4562

63+
/// Creates a configuration from a name and an optional URL for each
64+
/// formatter.
65+
///
66+
/// - Parameters:
67+
/// - name: User-visible name.
68+
/// - swiftFormat: SwiftFormat configuration URL, or `nil`.
69+
/// - uncrustify: Uncrustify configuration URL, or `nil`.
4670
public init( name: String, swiftFormat: URL?, uncrustify: URL? )
4771
{
4872
self.name = name
@@ -52,11 +76,17 @@ public class Configuration: NSObject, Codable
5276
super.init()
5377
}
5478

79+
/// A textual description including the configuration's name, for debugging.
5580
public override var description: String
5681
{
5782
"\( super.description ): \( self.name )"
5883
}
5984

85+
/// Compares two configurations by value.
86+
///
87+
/// - Parameter object: The object to compare against.
88+
/// - Returns: `true` when `object` is a `Configuration` with the same name
89+
/// and formatter URLs.
6090
public override func isEqual( _ object: Any? ) -> Bool
6191
{
6292
guard let configuration = object as? Configuration
@@ -75,6 +105,8 @@ public class Configuration: NSObject, Codable
75105
return false
76106
}
77107

108+
/// A hash derived from the name and formatter URLs, consistent with
109+
/// ``isEqual(_:)``.
78110
public override var hash: Int
79111
{
80112
var hasher = Hasher()
@@ -86,6 +118,11 @@ public class Configuration: NSObject, Codable
86118
return hasher.finalize()
87119
}
88120

121+
/// Downloads this configuration's formatter files into the shared cache.
122+
///
123+
/// Coalesces concurrent calls via the ``downloading`` flag (checked and set
124+
/// on the main queue), then fetches each non-`nil` URL on a background
125+
/// queue, clearing the flag when finished.
89126
public func download()
90127
{
91128
DispatchQueue.main.async
@@ -117,6 +154,15 @@ public class Configuration: NSObject, Codable
117154
}
118155
}
119156

157+
/// Downloads a single configuration file and writes it to the shared cache.
158+
///
159+
/// Rejects non-HTTPS URLs, names the cached file by the hash of its URL,
160+
/// and writes a `<hash>.sha256` sidecar holding the content hash so the
161+
/// cache can be integrity-checked on read. File writes are serialized
162+
/// through an `NSFileCoordinator`. Any failure is silently ignored, leaving
163+
/// the cache untouched.
164+
///
165+
/// - Parameter url: HTTPS URL of the configuration file to fetch.
120166
private func download( url: URL )
121167
{
122168
guard url.scheme?.lowercased() == "https",
@@ -154,6 +200,10 @@ public class Configuration: NSObject, Codable
154200
/// Fetches a configuration over HTTPS with an explicit timeout, returning
155201
/// the body only for a 2xx response. Runs synchronously; intended to be
156202
/// called from a background queue.
203+
///
204+
/// - Parameter url: URL of the configuration file to fetch.
205+
/// - Returns: The response body for a 2xx response, or `nil` on a transport
206+
/// error or non-2xx status.
157207
private static func fetch( url: URL ) -> Data?
158208
{
159209
var request = URLRequest( url: url, timeoutInterval: 30 )
@@ -189,6 +239,23 @@ public class Configuration: NSObject, Codable
189239
return result
190240
}
191241

242+
/// Provides local copies of the cached configuration files to a closure,
243+
/// then lets the caller clean them up.
244+
///
245+
/// Each available file is copied to a unique temporary location (its
246+
/// integrity verified against the stored content hash). If a configured URL
247+
/// has no valid cached copy, a fresh ``download()`` is triggered for next
248+
/// time. When neither file is available the `error` closure is called and
249+
/// `completion` is not. Otherwise `completion` receives the temporary URLs
250+
/// plus a `finished` closure that deletes them; the caller must invoke
251+
/// `finished` once done.
252+
///
253+
/// - Parameters:
254+
/// - completion: Called with the temporary `swiftFormat` / `uncrustify`
255+
/// URLs (either may be `nil`) and a `finished` cleanup
256+
/// closure.
257+
/// - error: Called instead of `completion` when no cached file is
258+
/// available.
192259
public func withConfigurations( completion: ( ( swiftFormat: URL?, uncrustify: URL?, finished: () -> Void ) ) -> Void, error: () -> Void )
193260
{
194261
let swiftFormat = self.copy( url: self.swiftFormat )
@@ -225,6 +292,19 @@ public class Configuration: NSObject, Codable
225292
completion( ( swiftFormat: swiftFormat, uncrustify: uncrustify, finished: finished ) )
226293
}
227294

295+
/// Copies a cached configuration file to a unique temporary URL after
296+
/// verifying its integrity.
297+
///
298+
/// Locates the cached file by the hash of `url`, and — when a `<hash>.sha256`
299+
/// sidecar exists — rejects the copy if the bytes no longer match, so a
300+
/// tampered or partially written cache is never fed to the formatter. File
301+
/// access is serialized through an `NSFileCoordinator`.
302+
///
303+
/// - Parameter url: The original configuration URL whose cached copy is
304+
/// wanted, or `nil`.
305+
/// - Returns: A temporary URL holding a fresh copy of the cached file, or
306+
/// `nil` if `url` is `nil`, nothing is cached, or the integrity
307+
/// check or copy fails.
228308
private func copy( url: URL? ) -> URL?
229309
{
230310
guard let url = url,

Shared/ConfigurationURLError.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ public enum ConfigurationURLError: LocalizedError, Equatable
3434
/// The URL is well-formed but does not use the `https` scheme.
3535
case insecure
3636

37+
/// A localized, user-facing message describing why the URL was rejected.
3738
public var errorDescription: String?
3839
{
3940
switch self

Shared/CursorPosition.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,17 @@ import Foundation
2828
/// convention of `XCSourceTextPosition` (columns are UTF-16 code-unit offsets).
2929
public struct CursorPosition: Equatable
3030
{
31+
/// Zero-based line index of the caret.
3132
public let line: Int
33+
34+
/// Zero-based column of the caret, measured in UTF-16 code units.
3235
public let column: Int
3336

37+
/// Creates a cursor position from a line index and column.
38+
///
39+
/// - Parameters:
40+
/// - line: Zero-based line index.
41+
/// - column: Zero-based column, in UTF-16 code units.
3442
public init( line: Int, column: Int )
3543
{
3644
self.line = line

Shared/Extensions/Data.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,11 @@
2525
import CryptoKit
2626
import Foundation
2727

28+
/// SHA-256 hashing helper for raw bytes.
2829
public extension Data
2930
{
31+
/// The SHA-256 digest of the bytes, formatted as an uppercase hexadecimal
32+
/// string.
3033
var sha256: String
3134
{
3235
SHA256.hash( data: self ).compactMap

Shared/Extensions/FileManager.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,13 @@
2424

2525
import Foundation
2626

27+
/// Access to the app group's shared container, used to exchange cached
28+
/// configuration files between the app and the editor extension.
2729
public extension FileManager
2830
{
31+
/// URL of the app group's shared container, used to exchange cached
32+
/// configuration files between the main app and the editor extension, or
33+
/// `nil` if the container is unavailable.
2934
static var sharedContainerURL: URL?
3035
{
3136
FileManager.default.containerURL( forSecurityApplicationGroupIdentifier: "326Y53CJMD.com.xs-labs.XcodeFormat.Shared" )

Shared/Extensions/String.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,11 @@
2424

2525
import Foundation
2626

27+
/// SHA-256 hashing helper for string contents.
2728
public extension String
2829
{
30+
/// The SHA-256 digest of the string's UTF-8 bytes as an uppercase
31+
/// hexadecimal string, or `nil` if the string cannot be UTF-8 encoded.
2932
var sha256: String?
3033
{
3134
self.data( using: .utf8 )?.sha256

Shared/Extensions/URL.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,12 @@
2424

2525
import Foundation
2626

27+
/// Hashing and validation helpers for configuration URLs.
2728
public extension URL
2829
{
30+
/// The SHA-256 digest of the URL's absolute string as an uppercase
31+
/// hexadecimal string, used to derive a stable cache file name for a
32+
/// configuration URL.
2933
var sha256: String?
3034
{
3135
self.absoluteString.sha256

Shared/FormatterError.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ public enum FormatterError: LocalizedError, Equatable
3535
/// its captured standard-error text.
3636
case failed( executable: String, status: Int32, message: String )
3737

38+
/// A localized, user-facing description of the failure, including the
39+
/// formatter's trimmed standard-error text when one is available.
3840
public var errorDescription: String?
3941
{
4042
switch self

0 commit comments

Comments
 (0)