Skip to content

fix(sonarcloud): resolve all issues - 0 violations#16

Merged
arediss merged 19 commits intomainfrom
fix/sonarcloud-issues
Feb 10, 2026
Merged

fix(sonarcloud): resolve all issues - 0 violations#16
arediss merged 19 commits intomainfrom
fix/sonarcloud-issues

Conversation

@arediss
Copy link
Owner

@arediss arediss commented Feb 10, 2026

Summary

Resolves all SonarCloud issues on the codebase: 26 CRITICAL + 63 MAJOR + ~150 MINOR → 0 violations. Quality gate now passes.

CRITICAL (26 resolved)

  • S3735 (17x): Remove void operators conflicting with SonarCloud
  • S3776 (5x): Reduce cognitive complexity (AuthenticationSection CC=41→15, App.tsx CC=25→12, SftpBrowser CC=16→10, PluginManager CC=16→10, sanitize CC=20→12)
  • S2004 (4x): Reduce nesting depth in App.tsx, SftpBrowser

MAJOR (63 resolved)

  • S3358 (24x): Replace nested ternaries with helper functions and early returns
  • S6848 (23x): Add ARIA roles to interactive elements
  • S6582 (3x): Use optional chaining
  • S6819 (18x): Replace ARIA roles with semantic HTML elements (dialog, output, aria-hidden)
  • S6847 (5x): Move event listeners off non-interactive elements
  • S6852 (4x): Add tabIndex to focusable interactive roles
  • S6845 (2x): Remove tabIndex from non-interactive elements
  • S2589 (1x): Remove always-truthy guard
  • Plus: S2933, S6535, S6836, S6479, S6853, S7785 fixes

MINOR (~150 resolved)

  • S6759 (52x): Mark component props as Readonly
  • S7764 (22x): Prefer globalThis over window
  • S1082 (17x): Add keyboard handlers to clickable elements
  • S7773 (15x): Use Number.parseInt/parseFloat
  • S1874 (13x): Remove incorrect @deprecated tags
  • S7735 (10x): Flip negated conditions
  • S3863 (8x): Consolidate duplicate imports
  • S7781 (4x): Use String.replaceAll
  • S7723 (4x): Use new Array()
  • S4323 (3x): Extract union types into type aliases
  • S7772 (3x): Use node: prefix for imports

Key changes

  • tsconfig.json: Target upgraded from ES2020 to ES2021 (enables replaceAll)
  • i18n/index.ts: Converted to top-level await
  • Modal components: Backdrop overlays use aria-hidden, dialog wrappers use native <dialog> element
  • Clickable divs: Converted to <button> elements where appropriate
  • AuthenticationSection: Split from SecuritySettings into focused sub-components
  • App.tsx, SftpBrowser, PluginManager, sanitize: Reduced cognitive complexity via extraction

16 commits

# Commit Scope
1 c66798c Remove void operators (S3735)
2 3431749 Split AuthenticationSection (S3776)
3 e3241cd Reduce complexity in App.tsx
4 baf9977 Reduce complexity in SftpBrowser
5 2fd9623 Reduce complexity in PluginManager/sanitize
6 5fc1c63 Miscellaneous MAJOR fixes
7 7aa9d51 Replace nested ternaries (S3358)
8 f4c2224 Add ARIA roles (S6848)
9 eb21928 Number.parseInt, replaceAll, node: imports
10 dde3733 globalThis over window
11 e48b4f3 Consolidate imports, type aliases, deprecated tags
12 cef3aa2 Readonly props + keyboard handlers
13 a8dff15 Flip negated conditions
14 6fbd43e Semantic HTML + remaining fixes
15 ffe3c8e Move keyboard handlers off dialogs
16 d908cd6 PromptModal Escape handler

Test plan

  • Visual test: All modals open/close correctly (Escape key, backdrop click)
  • Visual test: Command palette keyboard navigation works
  • Visual test: Settings > Security (vault, PIN, FIDO2, password change)
  • Visual test: Plugin modal interactions
  • Visual test: SFTP browser context menu
  • Visual test: Sidebar session right-click context menu
  • Visual test: Split pane resize handles work
  • SonarCloud quality gate: PASSED (0 violations)

Remove 24 void operator usages that were added for Qodana's
JSIgnoredPromiseFromCall rule but conflict with SonarCloud's S3735
(CRITICAL). SonarCloud is now the primary static analysis tool.
…exity

Extract PinSection, BiometricSection, SecurityKeySection, and
SecurityKeySetupContent as separate functions. Replaces nested
ternary chains with early returns. Cognitive complexity reduced
from 41 to ~10 per function (S3776 CRITICAL).
- Extract handleSftpConnectFromPending, buildJumpHostParams, and
  saveSessionAfterConnect from handleSshConnect (CC 25→~6, S3776)
- Replace sequential keyboard shortcut if-chains with data-driven
  shortcut table + matchesShortcut helper (CC 20→~2, S3776)
- Convert .then() chain to async/await in update check to fix
  nesting depth >4 (S2004)
- Extract handleFileUploaded and updateFileStatus from IIFE to
  fix function nesting depth >4 (S2004 x2)
- Extract getRowHighlight and getEditIndicator helpers to replace
  nested ternary chains, reducing cognitive complexity (S3776)
…anitize

- Extract removeEntriesByPlugin helper in PluginManager to
  deduplicate status bar and header action cleanup (CC 16→~10, S3776)
- Extract hasDangerousNodes and isDangerousAttribute in sanitize.ts,
  replace nested for/if chain with mutations.some() (CC 20→~8, S3776)
- S2933: mark PluginManager fields as readonly
- S6535: remove unnecessary escape in sanitize regex
- S6836: wrap lexical declaration in case block (PluginHost)
- S6582: use optional chaining in App.tsx (3 instances)
- S7785: convert i18n/main.tsx to top-level await
- S6479: replace array index keys with stable identifiers
- S6853: fix label accessibility in SshKeyManager
Extract nested ternary chains into helper functions and sub-components:
- BrowsePluginsTab: extract BrowsePluginsResults component
- InstalledPluginsTab: extract InstalledPluginsList component
- DeveloperPluginsTab: extract DevPluginsList component
- VaultSetupModal: extract getStepClassName, getPinStepInfo helpers
- TunnelSidebar: extract getTunnelTypeLabel, TunnelStatusIcon
- EmptyPaneSessions: extract getSessionItemClassName helper
- SftpBrowser: replace ternary chain with && conditions
- HostKeyModal, PaneGroupTabBar, TunnelManager: extract helpers
Add appropriate ARIA roles to non-native interactive elements:
- role="presentation" on overlay/backdrop click-to-close divs
- role="dialog" on CommandPalette dialog container
- role="menu" on context menus (Sidebar, SftpBrowser)
- role="separator" + tabIndex on SplitHandle resize handles
- role="presentation" on decorative clickable elements
@github-actions
Copy link

github-actions bot commented Feb 10, 2026

Qodana for JS

28 new problems were found

Inspection name Severity Problems
Mismatched JSDoc and function signature 🔶 Warning 2
Redundant 'if' statement 🔶 Warning 1
Result of method call returning a promise is ignored ◽️ Notice 24
Duplicated code fragment ◽️ Notice 1

☁️ View the detailed Qodana report

Contact Qodana team

Contact us at qodana-support@jetbrains.com

…73, S7781, S7772)

- Replace parseInt/parseFloat with Number.parseInt/Number.parseFloat
- Replace String#replace with String#replaceAll for global regex
- Use node: protocol prefix in script imports
- Update tsconfig target from ES2020 to ES2021 for replaceAll support
Replace window.* with globalThis.* for platform-agnostic global access.
Add global type declaration for SimplyTermPlugins in PluginManager.
…(S3863, S4323, S1874)

- Merge duplicate imports from same module
- Extract union types into named type aliases in SerialConnectionForm
- Replace @deprecated with legacy note on SidebarSection types (still in use)
…6759, S1082)

- Wrap all component props types with Readonly<> (52 instances)
- Add onKeyDown handlers to elements with onClick (17 instances)
  - Backdrop overlays: Escape key to close
  - Context menus: Escape key to close
  - Interactive elements: Enter/Space activation
Rewrite if/else and ternary patterns to test positive condition first.
…sues (S6819, S6847, S6852, S6845, S6759, S4323, S2589, S7785)

- Replace role="presentation" with aria-hidden="true" on backdrop overlays
- Convert role="dialog" divs to native <dialog> elements
- Convert role="button" divs to <button> elements (Sidebar, PluginSidebarSection)
- Replace role="status" with <output> element (PluginWidget)
- Remove unnecessary role="group" and role="separator"
- Add tabIndex to focusable interactive roles (menu, tablist)
- Mark remaining component props as Readonly<>
- Use type aliases for union types in SerialConnectionForm
- Remove always-truthy guard in BrowsePluginsTab
- Convert .then() to top-level await in i18n fallback loading
… (S6847)

- CommandPalette: move onKeyDown from <dialog> to the focused <input>
- PluginModal: replace onKeyDown with useEffect document listener
- PromptModal: move onKeyDown from <dialog> to inner <form>
@arediss arediss changed the title Fix SonarCloud issues: 26 CRITICAL + 63 MAJOR fix(sonarcloud): resolve all issues - 0 violations Feb 10, 2026
…sted SFTP button

HTML forbids <button> inside <button>. The session item wrapper must be a
<div role="button"> so the inner SFTP <button> is valid.
In React StrictMode, effects run twice (mount→cleanup→remount).
The isMountedRef pattern broke because cleanup set false but remount
didn't reset to true, causing all async callbacks to bail out silently.
This caused SFTP browser to show infinite loading spinner, and would
affect tunnel components similarly.
Split session item into two sibling buttons (connect + SFTP) inside a
plain div container. Fixes both the HTML nesting violation (<button>
inside <button>) and SonarCloud S6819 (div role="button").
@sonarqubecloud
Copy link

@arediss arediss merged commit f0237c5 into main Feb 10, 2026
2 checks passed
@arediss arediss deleted the fix/sonarcloud-issues branch February 10, 2026 15:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant