swift-code-reviewer-skill 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/CHANGELOG.md +43 -169
  2. package/README.md +43 -2
  3. package/SKILL.md +194 -711
  4. package/bin/install.js +1 -1
  5. package/package.json +2 -1
  6. package/references/agent-loop-feedback.md +148 -0
  7. package/references/companion-skills.md +70 -0
  8. package/references/spec-adherence.md +157 -0
  9. package/skills/README.md +43 -0
  10. package/skills/swift-concurrency/NOTICE.md +18 -0
  11. package/skills/swift-concurrency/SKILL.md +235 -0
  12. package/skills/swift-concurrency/references/actors.md +640 -0
  13. package/skills/swift-concurrency/references/async-await-basics.md +249 -0
  14. package/skills/swift-concurrency/references/async-sequences.md +635 -0
  15. package/skills/swift-concurrency/references/core-data.md +533 -0
  16. package/skills/swift-concurrency/references/glossary.md +96 -0
  17. package/skills/swift-concurrency/references/linting.md +38 -0
  18. package/skills/swift-concurrency/references/memory-management.md +542 -0
  19. package/skills/swift-concurrency/references/migration.md +721 -0
  20. package/skills/swift-concurrency/references/performance.md +574 -0
  21. package/skills/swift-concurrency/references/sendable.md +578 -0
  22. package/skills/swift-concurrency/references/tasks.md +604 -0
  23. package/skills/swift-concurrency/references/testing.md +565 -0
  24. package/skills/swift-concurrency/references/threading.md +452 -0
  25. package/skills/swift-expert/NOTICE.md +18 -0
  26. package/skills/swift-expert/SKILL.md +226 -0
  27. package/skills/swift-expert/references/async-concurrency.md +363 -0
  28. package/skills/swift-expert/references/memory-performance.md +380 -0
  29. package/skills/swift-expert/references/protocol-oriented.md +357 -0
  30. package/skills/swift-expert/references/swiftui-patterns.md +294 -0
  31. package/skills/swift-expert/references/testing-patterns.md +402 -0
  32. package/skills/swift-testing/NOTICE.md +18 -0
  33. package/skills/swift-testing/SKILL.md +295 -0
  34. package/skills/swift-testing/references/async-testing.md +245 -0
  35. package/skills/swift-testing/references/dump-snapshot-testing.md +265 -0
  36. package/skills/swift-testing/references/fixtures.md +193 -0
  37. package/skills/swift-testing/references/integration-testing.md +189 -0
  38. package/skills/swift-testing/references/migration-xctest.md +301 -0
  39. package/skills/swift-testing/references/parameterized-tests.md +171 -0
  40. package/skills/swift-testing/references/snapshot-testing.md +201 -0
  41. package/skills/swift-testing/references/test-doubles.md +243 -0
  42. package/skills/swift-testing/references/test-organization.md +231 -0
  43. package/skills/swiftui-expert-skill/NOTICE.md +18 -0
  44. package/skills/swiftui-expert-skill/SKILL.md +281 -0
  45. package/skills/swiftui-expert-skill/references/accessibility-patterns.md +151 -0
  46. package/skills/swiftui-expert-skill/references/animation-advanced.md +403 -0
  47. package/skills/swiftui-expert-skill/references/animation-basics.md +284 -0
  48. package/skills/swiftui-expert-skill/references/animation-transitions.md +326 -0
  49. package/skills/swiftui-expert-skill/references/charts-accessibility.md +135 -0
  50. package/skills/swiftui-expert-skill/references/charts.md +602 -0
  51. package/skills/swiftui-expert-skill/references/image-optimization.md +203 -0
  52. package/skills/swiftui-expert-skill/references/latest-apis.md +464 -0
  53. package/skills/swiftui-expert-skill/references/layout-best-practices.md +266 -0
  54. package/skills/swiftui-expert-skill/references/liquid-glass.md +414 -0
  55. package/skills/swiftui-expert-skill/references/list-patterns.md +394 -0
  56. package/skills/swiftui-expert-skill/references/macos-scenes.md +318 -0
  57. package/skills/swiftui-expert-skill/references/macos-views.md +357 -0
  58. package/skills/swiftui-expert-skill/references/macos-window-styling.md +303 -0
  59. package/skills/swiftui-expert-skill/references/performance-patterns.md +403 -0
  60. package/skills/swiftui-expert-skill/references/scroll-patterns.md +293 -0
  61. package/skills/swiftui-expert-skill/references/sheet-navigation-patterns.md +363 -0
  62. package/skills/swiftui-expert-skill/references/state-management.md +417 -0
  63. package/skills/swiftui-expert-skill/references/view-structure.md +389 -0
  64. package/skills/swiftui-ui-patterns/NOTICE.md +18 -0
  65. package/skills/swiftui-ui-patterns/SKILL.md +95 -0
  66. package/skills/swiftui-ui-patterns/references/app-wiring.md +201 -0
  67. package/skills/swiftui-ui-patterns/references/async-state.md +96 -0
  68. package/skills/swiftui-ui-patterns/references/components-index.md +50 -0
  69. package/skills/swiftui-ui-patterns/references/controls.md +57 -0
  70. package/skills/swiftui-ui-patterns/references/deeplinks.md +66 -0
  71. package/skills/swiftui-ui-patterns/references/focus.md +90 -0
  72. package/skills/swiftui-ui-patterns/references/form.md +97 -0
  73. package/skills/swiftui-ui-patterns/references/grids.md +71 -0
  74. package/skills/swiftui-ui-patterns/references/haptics.md +71 -0
  75. package/skills/swiftui-ui-patterns/references/input-toolbar.md +51 -0
  76. package/skills/swiftui-ui-patterns/references/lightweight-clients.md +93 -0
  77. package/skills/swiftui-ui-patterns/references/list.md +86 -0
  78. package/skills/swiftui-ui-patterns/references/loading-placeholders.md +38 -0
  79. package/skills/swiftui-ui-patterns/references/macos-settings.md +71 -0
  80. package/skills/swiftui-ui-patterns/references/matched-transitions.md +59 -0
  81. package/skills/swiftui-ui-patterns/references/media.md +73 -0
  82. package/skills/swiftui-ui-patterns/references/menu-bar.md +101 -0
  83. package/skills/swiftui-ui-patterns/references/navigationstack.md +159 -0
  84. package/skills/swiftui-ui-patterns/references/overlay.md +45 -0
  85. package/skills/swiftui-ui-patterns/references/performance.md +62 -0
  86. package/skills/swiftui-ui-patterns/references/previews.md +48 -0
  87. package/skills/swiftui-ui-patterns/references/scroll-reveal.md +133 -0
  88. package/skills/swiftui-ui-patterns/references/scrollview.md +87 -0
  89. package/skills/swiftui-ui-patterns/references/searchable.md +71 -0
  90. package/skills/swiftui-ui-patterns/references/sheets.md +155 -0
  91. package/skills/swiftui-ui-patterns/references/split-views.md +72 -0
  92. package/skills/swiftui-ui-patterns/references/tabview.md +114 -0
  93. package/skills/swiftui-ui-patterns/references/theming.md +71 -0
  94. package/skills/swiftui-ui-patterns/references/title-menus.md +93 -0
  95. package/skills/swiftui-ui-patterns/references/top-bar.md +49 -0
@@ -0,0 +1,363 @@
1
+ # Async/Await Concurrency
2
+
3
+ > Reference for: Swift Expert
4
+ > Load when: async/await, actors, structured concurrency, Task management
5
+
6
+ ## Async/Await Basics
7
+
8
+ ```swift
9
+ // Async function
10
+ func fetchUser(id: Int) async throws -> User {
11
+ let url = URL(string: "https://api.example.com/users/\(id)")!
12
+ let (data, _) = try await URLSession.shared.data(from: url)
13
+ return try JSONDecoder().decode(User.self, from: data)
14
+ }
15
+
16
+ // Calling async functions
17
+ func loadUserData() async {
18
+ do {
19
+ let user = try await fetchUser(id: 123)
20
+ print("Loaded: \(user.name)")
21
+ } catch {
22
+ print("Error: \(error)")
23
+ }
24
+ }
25
+
26
+ // Multiple concurrent operations
27
+ func fetchMultipleUsers(ids: [Int]) async throws -> [User] {
28
+ try await withThrowingTaskGroup(of: User.self) { group in
29
+ for id in ids {
30
+ group.addTask {
31
+ try await fetchUser(id: id)
32
+ }
33
+ }
34
+
35
+ var users: [User] = []
36
+ for try await user in group {
37
+ users.append(user)
38
+ }
39
+ return users
40
+ }
41
+ }
42
+ ```
43
+
44
+ ## Actors
45
+
46
+ ```swift
47
+ // Actor for thread-safe state management
48
+ actor UserCache {
49
+ private var cache: [Int: User] = [:]
50
+ private var inProgress: [Int: Task<User, Error>] = [:]
51
+
52
+ func user(id: Int) async throws -> User {
53
+ // Check cache first
54
+ if let cached = cache[id] {
55
+ return cached
56
+ }
57
+
58
+ // Check if already loading
59
+ if let task = inProgress[id] {
60
+ return try await task.value
61
+ }
62
+
63
+ // Start new load
64
+ let task = Task {
65
+ try await fetchUser(id: id)
66
+ }
67
+ inProgress[id] = task
68
+
69
+ do {
70
+ let user = try await task.value
71
+ cache[id] = user
72
+ inProgress.removeValue(forKey: id)
73
+ return user
74
+ } catch {
75
+ inProgress.removeValue(forKey: id)
76
+ throw error
77
+ }
78
+ }
79
+
80
+ func clearCache() {
81
+ cache.removeAll()
82
+ }
83
+ }
84
+
85
+ // Usage
86
+ let cache = UserCache()
87
+ let user = try await cache.user(id: 123)
88
+ ```
89
+
90
+ ## MainActor
91
+
92
+ ```swift
93
+ // UI updates must happen on main thread
94
+ @MainActor
95
+ class ViewModel: ObservableObject {
96
+ @Published var users: [User] = []
97
+ @Published var isLoading = false
98
+
99
+ func loadUsers() async {
100
+ isLoading = true
101
+ defer { isLoading = false }
102
+
103
+ do {
104
+ // This async work happens off main thread
105
+ let loadedUsers = try await fetchMultipleUsers(ids: [1, 2, 3])
106
+
107
+ // Property updates happen on main thread automatically
108
+ users = loadedUsers
109
+ } catch {
110
+ print("Error: \(error)")
111
+ }
112
+ }
113
+ }
114
+
115
+ // Isolated functions
116
+ @MainActor
117
+ func updateUI() {
118
+ // This always runs on main thread
119
+ }
120
+
121
+ // Non-isolated functions in MainActor type
122
+ @MainActor
123
+ class DataManager {
124
+ var data: [String] = []
125
+
126
+ // Runs on main thread
127
+ func updateData(_ newData: [String]) {
128
+ data = newData
129
+ }
130
+
131
+ // Can run on any thread
132
+ nonisolated func processData(_ input: String) -> String {
133
+ return input.uppercased()
134
+ }
135
+ }
136
+ ```
137
+
138
+ ## Structured Concurrency
139
+
140
+ ```swift
141
+ // Task groups for dynamic concurrency
142
+ func downloadImages(urls: [URL]) async throws -> [UIImage] {
143
+ try await withThrowingTaskGroup(of: (Int, UIImage).self) { group in
144
+ for (index, url) in urls.enumerated() {
145
+ group.addTask {
146
+ let (data, _) = try await URLSession.shared.data(from: url)
147
+ guard let image = UIImage(data: data) else {
148
+ throw ImageError.invalidData
149
+ }
150
+ return (index, image)
151
+ }
152
+ }
153
+
154
+ var images = [UIImage?](repeating: nil, count: urls.count)
155
+ for try await (index, image) in group {
156
+ images[index] = image
157
+ }
158
+
159
+ return images.compactMap { $0 }
160
+ }
161
+ }
162
+
163
+ // Parallel async-let
164
+ func loadDashboard() async throws -> Dashboard {
165
+ async let user = fetchUser(id: currentUserID)
166
+ async let posts = fetchPosts()
167
+ async let notifications = fetchNotifications()
168
+
169
+ return try await Dashboard(
170
+ user: user,
171
+ posts: posts,
172
+ notifications: notifications
173
+ )
174
+ }
175
+ ```
176
+
177
+ ## Task Management
178
+
179
+ ```swift
180
+ // Detached tasks
181
+ func backgroundWork() {
182
+ Task.detached(priority: .background) {
183
+ // Runs independently, doesn't inherit context
184
+ await performHeavyComputation()
185
+ }
186
+ }
187
+
188
+ // Cancellation
189
+ class DataLoader {
190
+ private var loadTask: Task<Void, Never>?
191
+
192
+ func startLoading() {
193
+ loadTask?.cancel()
194
+
195
+ loadTask = Task {
196
+ do {
197
+ for try await item in itemStream() {
198
+ // Check for cancellation
199
+ try Task.checkCancellation()
200
+
201
+ await process(item)
202
+
203
+ // Alternative cancellation check
204
+ if Task.isCancelled {
205
+ break
206
+ }
207
+ }
208
+ } catch is CancellationError {
209
+ print("Task cancelled")
210
+ } catch {
211
+ print("Error: \(error)")
212
+ }
213
+ }
214
+ }
215
+
216
+ func stopLoading() {
217
+ loadTask?.cancel()
218
+ loadTask = nil
219
+ }
220
+ }
221
+
222
+ // Task priorities
223
+ Task(priority: .high) {
224
+ await criticalWork()
225
+ }
226
+
227
+ Task(priority: .low) {
228
+ await backgroundWork()
229
+ }
230
+ ```
231
+
232
+ ## AsyncSequence
233
+
234
+ ```swift
235
+ // Custom AsyncSequence
236
+ struct NumberSequence: AsyncSequence {
237
+ typealias Element = Int
238
+ let range: Range<Int>
239
+
240
+ struct AsyncIterator: AsyncIteratorProtocol {
241
+ var current: Int
242
+ let end: Int
243
+
244
+ mutating func next() async -> Int? {
245
+ guard current < end else { return nil }
246
+
247
+ // Simulate async work
248
+ try? await Task.sleep(for: .milliseconds(100))
249
+
250
+ defer { current += 1 }
251
+ return current
252
+ }
253
+ }
254
+
255
+ func makeAsyncIterator() -> AsyncIterator {
256
+ AsyncIterator(current: range.lowerBound, end: range.upperBound)
257
+ }
258
+ }
259
+
260
+ // Usage
261
+ for await number in NumberSequence(range: 0..<10) {
262
+ print(number)
263
+ }
264
+
265
+ // Async stream
266
+ func eventStream() -> AsyncStream<Event> {
267
+ AsyncStream { continuation in
268
+ let observer = NotificationCenter.default.addObserver(
269
+ forName: .eventOccurred,
270
+ object: nil,
271
+ queue: nil
272
+ ) { notification in
273
+ if let event = notification.object as? Event {
274
+ continuation.yield(event)
275
+ }
276
+ }
277
+
278
+ continuation.onTermination = { _ in
279
+ NotificationCenter.default.removeObserver(observer)
280
+ }
281
+ }
282
+ }
283
+ ```
284
+
285
+ ## Sendable Protocol
286
+
287
+ ```swift
288
+ // Sendable types can be safely passed across concurrency domains
289
+ struct User: Sendable {
290
+ let id: Int
291
+ let name: String
292
+ }
293
+
294
+ // Non-Sendable by default (has mutable state)
295
+ class ViewModel {
296
+ var data: [String] = []
297
+ }
298
+
299
+ // Make it Sendable with @unchecked (use carefully!)
300
+ class SafeViewModel: @unchecked Sendable {
301
+ private let lock = NSLock()
302
+ private var _data: [String] = []
303
+
304
+ var data: [String] {
305
+ lock.lock()
306
+ defer { lock.unlock() }
307
+ return _data
308
+ }
309
+
310
+ func setData(_ newData: [String]) {
311
+ lock.lock()
312
+ defer { lock.unlock() }
313
+ _data = newData
314
+ }
315
+ }
316
+
317
+ // Generic with Sendable constraint
318
+ func processData<T: Sendable>(_ data: T) async -> T {
319
+ // Can safely pass data across concurrency boundaries
320
+ await Task.detached {
321
+ return data
322
+ }.value
323
+ }
324
+ ```
325
+
326
+ ## Continuations
327
+
328
+ ```swift
329
+ // Bridging callback-based APIs to async/await
330
+ func fetchDataAsync() async throws -> Data {
331
+ try await withCheckedThrowingContinuation { continuation in
332
+ fetchDataWithCallback { result in
333
+ switch result {
334
+ case .success(let data):
335
+ continuation.resume(returning: data)
336
+ case .failure(let error):
337
+ continuation.resume(throwing: error)
338
+ }
339
+ }
340
+ }
341
+ }
342
+
343
+ // Unsafe continuations for performance-critical code
344
+ func unsafeFetchDataAsync() async -> Data {
345
+ await withUnsafeContinuation { continuation in
346
+ fetchDataWithCallback { data in
347
+ continuation.resume(returning: data)
348
+ }
349
+ }
350
+ }
351
+ ```
352
+
353
+ ## Best Practices
354
+
355
+ - Use actors for mutable shared state
356
+ - Prefer async/await over completion handlers
357
+ - Use MainActor for UI-related code
358
+ - Leverage structured concurrency (task groups, async-let)
359
+ - Check for cancellation in long-running tasks
360
+ - Mark types as Sendable when safe
361
+ - Use continuations to bridge legacy async code
362
+ - Avoid blocking in async contexts
363
+ - Use Task.detached sparingly (breaks structured concurrency)