Commit fec160e859

fec160e859db3341cfaf8920b4f29712db4dd7f5

parent: 9e848efa90

Unsigned

cmc <hello@cleberg.net> · 2026-07-16 15:18 UTC

chore: clear the actionable SonarCloud code smells

- S1871: merge the identical .home / .recentActivity deep-link cases in
  RootView — recent activity is a section of Home, not its own screen.
- S1186: comment the two intentionally-empty Cancel buttons
  (PatchsetDetailView, TicketDetailView) and the empty URLProtocol
  stopLoading override in APICacheTests.
- S108: comment the expected-miss catch block in APICacheTests.
- S1172: rename the unused url parameter in mimeType(for:) to _.
- S4624: extract the nested template literal in the deep-link builders
  (background.js, content.js) to a pathSegment variable.

Left as Won't Fix, with reasons: the 35 hardcoded-URI warnings (a
one-forge client and its literal-URL tests), executeCached's 8 params
(38 call sites, no benefit), the forceRefresh S1172 pair (fixed as a
real bug instead), S1481 on ArtifactsView (false positive — $vm.error
is used), and S7785 (top-level await would break a classic content
script).

Layout: unified · split

Hutch/App/RootView.swift +3 −5
@@ -198,11 +198,9 @@ struct RootView: View {
198 } 198 }
199 199
200 switch link { 200 switch link {
201 case .home: 201 // Recent activity is a section of the Home tab, not a screen of its
202 homePath = NavigationPath() 202 // own, so its intent/widget deep link lands on Home like .home does.
203 appState.selectedTab = .home 203 case .home, .recentActivity:
204
205 case .recentActivity:
206 homePath = NavigationPath() 204 homePath = NavigationPath()
207 appState.selectedTab = .home 205 appState.selectedTab = .home
208 206
Hutch/Views/Patchsets/PatchsetDetailView.swift +1 −1
@@ -71,7 +71,7 @@ struct PatchsetDetailView: View {
71 Task { await viewModel.updateStatus(to: status) } 71 Task { await viewModel.updateStatus(to: status) }
72 } 72 }
73 } 73 }
74 Button("Cancel", role: .cancel) {} 74 Button("Cancel", role: .cancel) {} // dismisses the dialog; no action needed
75 } 75 }
76 .alert( 76 .alert(
77 "Couldn't Update Patchset", 77 "Couldn't Update Patchset",
Hutch/Views/Repositories/RepositoryDetailViewModel.swift +1 −1
@@ -627,7 +627,7 @@ final class RepositoryDetailViewModel {
627 627
628 /// Artifacts are release tarballs and signatures rather than media, so a 628 /// Artifacts are release tarballs and signatures rather than media, so a
629 /// generic binary type is honest more often than guessing from the extension. 629 /// generic binary type is honest more often than guessing from the extension.
630 private nonisolated static func mimeType(for url: URL) -> String { 630 private nonisolated static func mimeType(for _: URL) -> String {
631 "application/octet-stream" 631 "application/octet-stream"
632 } 632 }
633 633
Hutch/Views/Tickets/TicketDetailView.swift +1 −1
@@ -204,7 +204,7 @@ struct TicketDetailView: View {
204 } 204 }
205 } 205 }
206 } 206 }
207 Button("Cancel", role: .cancel) {} 207 Button("Cancel", role: .cancel) {} // dismisses the dialog; no action needed
208 } message: { 208 } message: {
209 Text("This permanently deletes the ticket and its comments. This cannot be undone.") 209 Text("This permanently deletes the ticket and its comments. This cannot be undone.")
210 } 210 }
HutchSafariExtension/Resources/background.js +2 −1
@@ -68,7 +68,8 @@ function hutchDeepLinkFor(rawURL) {
68 68
69 const path = deepLinkPath(url.hostname, normalizedPath(url.pathname)); 69 const path = deepLinkPath(url.hostname, normalizedPath(url.pathname));
70 const service = deepLinkService(url.hostname, path); 70 const service = deepLinkService(url.hostname, path);
71 return `hutch://${service}${path ? `/${path}` : ""}${url.search}${url.hash}`; 71 const pathSegment = path ? `/${path}` : "";
72 return `hutch://${service}${pathSegment}${url.search}${url.hash}`;
72} 73}
73 74
74function showUnsupportedMessage(tabId) { 75function showUnsupportedMessage(tabId) {
HutchSafariExtension/Resources/content.js +2 −1
@@ -63,7 +63,8 @@ function hutchDeepLinkForLocation() {
63 63
64 const path = hutchDeepLinkPath(location.hostname, hutchNormalizedPath(location.pathname)); 64 const path = hutchDeepLinkPath(location.hostname, hutchNormalizedPath(location.pathname));
65 const service = hutchDeepLinkService(location.hostname, path); 65 const service = hutchDeepLinkService(location.hostname, path);
66 return `hutch://${service}${path ? `/${path}` : ""}${location.search}${location.hash}`; 66 const pathSegment = path ? `/${path}` : "";
67 return `hutch://${service}${pathSegment}${location.search}${location.hash}`;
67} 68}
68 69
69function storageGet(defaults) { 70function storageGet(defaults) {
HutchTests/APICacheTests.swift +2 −1
@@ -256,6 +256,7 @@ struct APICacheTests {
256 _ = try await cache.read(cacheKey: key) 256 _ = try await cache.read(cacheKey: key)
257 Issue.record("Expected cache miss for \(key).") 257 Issue.record("Expected cache miss for \(key).")
258 } catch APICacheError.miss { 258 } catch APICacheError.miss {
259 // expected: a miss is the success path here
259 } catch { 260 } catch {
260 Issue.record("Unexpected error for \(key): \(error).") 261 Issue.record("Unexpected error for \(key): \(error).")
261 } 262 }
@@ -293,7 +294,7 @@ private final class CachedURLProtocol: URLProtocol, @unchecked Sendable {
293 } 294 }
294 } 295 }
295 296
296 override func stopLoading() {} 297 override func stopLoading() {} // required override; nothing to tear down
297 298
298 static func reset(responses: [CachedURLProtocolResponse], responseDelay: TimeInterval = 0) { 299 static func reset(responses: [CachedURLProtocolResponse], responseDelay: TimeInterval = 0) {
299 Self.responses = responses 300 Self.responses = responses