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 | 200 | switch link { |
| 201 | | case .home: |
| 202 | | homePath = NavigationPath() |
| 203 | | appState.selectedTab = .home |
| 204 | | |
| 205 | | case .recentActivity: |
| 201 | // Recent activity is a section of the Home tab, not a screen of its |
| 202 | // own, so its intent/widget deep link lands on Home like .home does. |
| 203 | case .home, .recentActivity: |
| 206 | 204 | homePath = NavigationPath() |
| 207 | 205 | appState.selectedTab = .home |
| 208 | 206 | |
Hutch/Views/Patchsets/PatchsetDetailView.swift
+1 −1
| @@ -71,7 +71,7 @@ struct PatchsetDetailView: View { |
| 71 | 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 | 76 | .alert( |
| 77 | 77 | "Couldn't Update Patchset", |
Hutch/Views/Repositories/RepositoryDetailViewModel.swift
+1 −1
| @@ -627,7 +627,7 @@ final class RepositoryDetailViewModel { |
| 627 | 627 | |
| 628 | 628 | /// Artifacts are release tarballs and signatures rather than media, so a |
| 629 | 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 | 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 | 208 | } message: { |
| 209 | 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 | 69 | const path = deepLinkPath(url.hostname, normalizedPath(url.pathname)); |
| 70 | 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 | |
| 74 | 75 | function showUnsupportedMessage(tabId) { |
HutchSafariExtension/Resources/content.js
+2 −1
| @@ -63,7 +63,8 @@ function hutchDeepLinkForLocation() { |
| 63 | 63 | |
| 64 | 64 | const path = hutchDeepLinkPath(location.hostname, hutchNormalizedPath(location.pathname)); |
| 65 | 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 | |
| 69 | 70 | function storageGet(defaults) { |
HutchTests/APICacheTests.swift
+2 −1
| @@ -256,6 +256,7 @@ struct APICacheTests { |
| 256 | 256 | _ = try await cache.read(cacheKey: key) |
| 257 | 257 | Issue.record("Expected cache miss for \(key).") |
| 258 | 258 | } catch APICacheError.miss { |
| 259 | // expected: a miss is the success path here |
| 259 | 260 | } catch { |
| 260 | 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 | 299 | static func reset(responses: [CachedURLProtocolResponse], responseDelay: TimeInterval = 0) { |
| 299 | 300 | Self.responses = responses |