Skip to content

refactor(sonar): reduce cognitive complexity and add test coverage#953

Merged
stephanj merged 11 commits intomasterfrom
sonarlint-fixes
Feb 21, 2026
Merged

refactor(sonar): reduce cognitive complexity and add test coverage#953
stephanj merged 11 commits intomasterfrom
sonarlint-fixes

Conversation

@stephanj
Copy link
Copy Markdown
Collaborator

Summary

  • Refactored 40+ Java files across MCP, CLI, spec, scanner, UI, and webview components to reduce SonarLint cognitive complexity (S3776) below threshold
  • Fixed SonarLint issues S1602, S6204, S6205, S1192, S1141 across various files
  • Added unit tests for PSI tools, language scanners, MCP components, and UI panels
  • Fixed CEF rendering pipeline stall after long idle periods (e.g. Ollama cold-start)
  • Fixed build failures in GPT4All, Mistral, and OpenRouter factory tests
  • Fixed backlog reassignTo parameter validation before milestone state changes

Changes

Refactoring (SonarLint S3776 – cognitive complexity)

  • MCPConfigurationParser, MCPMarketplaceDialog, MCPServerDialog, MCPSettingsComponent, MCPToolsManager, MCPListenerService
  • CliTaskExecutorService, StreamingPromptStrategy, TaskDependencySorter
  • SpecTaskRunnerService, SpecStatisticsPanel, SpecFrontmatterParser, SpecContextBuilder, BacklogConfigService, BacklogTaskToolExecutor, BacklogMilestoneToolExecutor
  • CachedProjectScanner, FileSelectionPanelFactory, FindDefinitionToolExecutor, FindSymbolsToolExecutor, GitignoreParser, GlobTool, BuildSystemDetector, FuzzySearchHelper
  • Language scanners: GoProjectScannerExtension, JavaScriptProjectScannerExtension, KotlinProjectScannerExtension, CppProjectScannerExtension, PythonProjectScannerExtension
  • UI: LLMProvidersConfigurable, CompletionSettingsComponent, FileEntryComponent, CommandAutoCompleteTextField
  • Webview: WebViewJavaScriptExecutor, WebViewBrowserStateMonitor, WebViewBrowserInitializer, ConversationWebViewController

New Tests

  • FindDefinitionToolExecutorTest
  • CppProjectScannerExtensionTest, GoProjectScannerExtensionTest, JavaScriptProjectScannerExtensionTest, KotlinProjectScannerExtensionTest
  • CachedProjectScannerTest
  • MCPToolsManagerTest
  • FileSelectionPanelFactoryTest
  • LLMProvidersConfigurableTest
  • MCPMarketplaceDialogFilterTest, MCPServerDialogEnvVarTest
  • CliTaskExecutorServiceTest, CompletionSettingsComponentTest

Bug Fixes

  • WebViewJavaScriptExecutor: schedule aggressive repaint (invalidate + revalidate + repaint up the parent chain) 150 ms after JS execution when idle > 5 s, to wake CEF's rendering pipeline after Ollama cold-starts
  • Factory tests: resolve build failures in GPT4All, Mistral, and OpenRouter
  • Backlog: validate reassignTo parameter before milestone state changes

Test plan

  • Run ./gradlew test — all existing and new tests pass
  • Run ./gradlew verifyPlugin — plugin verification succeeds
  • Manually test with a local Ollama model that requires a cold-start: verify the first streamed response renders without needing to click/move the panel
  • Verify MCP tool execution still works (both stdio and SSE transports)
  • Verify language scanner refactors produce the same output as before on a real project

🤖 Generated with Claude Code

stephanj and others added 11 commits February 21, 2026 09:50
Add a new "Creating Backlog Tasks via Java API" section to the integration
overview and a matching subsection in the Feb 18 blog post, documenting
the ExternalTaskService reflection-based API introduced in 3a022c1.

Covers: reflection call pattern, parameter table, return value (task ID),
auto-init/ID-allocation behaviour, and when to prefer this over direct
file writing (simpler path vs richer metadata fields).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Refactor FindSymbolsToolExecutor, GoProjectScannerExtension,
JavaScriptProjectScannerExtension, GlobTool, GitignoreParser,
FuzzySearchHelper, and FileSelectionPanelFactory to address
SonarQube java:S3776 cognitive complexity violations by extracting
helper methods and simplifying control flow.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously, when taskHandling='reassign' was called without a reassignTo
value, the milestone was already removed from the config before the
missing parameter was detected. Now the parameter is validated upfront,
before any state is modified, to prevent partial state corruption.

Also extracted applyTaskHandling() and updateMatchingTasks() helpers
to reduce cognitive complexity (SonarQube S3776).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ner, and UI

Extract methods to address SonarQube S3776 cognitive complexity violations
across multiple classes:

- BacklogConfigService: introduce ParseState inner class; extract
  processListItem, processMilestoneListItem, processKeyValue,
  flushParseState, and parseNumericSuffix helpers; use TASKS_DIR constant
- TaskDependencySorter: extract buildSelectedIds, buildSelectedById,
  buildAllById, initializeGraphNodes, addInternalEdges, buildInitialQueue,
  drainQueue, layerComparator, processLayerDependents, checkForCycles,
  and resolveTaskId; eliminates duplicated BFS logic between sort() and layers()
- SpecTaskRunnerService: extract formatSkipLine (now package-visible for
  testing) and printToCliConsole helpers
- StreamingPromptStrategy: extract createStreamingResponseHandler,
  executeStreamingInBackground, resolveToolProvider, buildAssistant, and
  logToolExecution; remove unused imports
- KotlinProjectScannerExtension: extract getBuildCommands,
  addFrameworkCommands, addAndroidCommands, addMultiplatformCommands,
  and addCodeQualityCommands
- SpecStatisticsPanel: extract addEmptyState, addSummaryRow,
  addProgressBarRow, addPriorityRow, buildPriorityText, addChecklistRow,
  and buildChecklistText; also extract standardPriorities list to avoid
  repeated allocations
- LLMProvidersConfigurable: extract isAnyApiKeyEnabled,
  hasEnabledMainCloudKey, hasEnabledAuxCloudKey, and
  hasEnabledAwsOrAzureKey helpers
- SpecService.buildTaskFileName: lowercase the ID part so task filenames
  are always lowercase regardless of the prefix casing stored in config

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- BacklogConfigServiceTest: update getNextTaskId assertions from 'TASK-N'
  to 'task-N' following the lowercase task_prefix default introduced in
  5aa4864
- SpecServiceTest: update createTask ID assertion to expect 'task-' prefix
  and add coverage for lowercase filenames produced by buildTaskFileName
- SpecContextBuilderTest: change startsWith to contains for the CLI
  instruction test since buildCliInstruction now prepends a
  BACKLOG_WORKFLOW_INSTRUCTION preamble before the task text
- SpecTaskRunnerServiceTest: add three unit tests for the newly extracted
  formatSkipLine helper (with reason, null reason, and empty title)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…I components

Extract helper methods and simplify branching logic to address SonarQube S3776
(cognitive complexity) warnings across:
- BacklogTaskToolExecutor, BuildSystemDetector, FindDefinitionToolExecutor
- CppProjectScannerExtension, CachedProjectScanner
- ClaudeStreamJsonParser, CliTaskExecutorService
- MCPConfigurationParser, MCPListenerService, MCPToolsManager
- BacklogConfigService, SpecContextBuilder, SpecFrontmatterParser
- FileSelectionPanelFactory, CompletionSettingsComponent
- MCPSettingsComponent, MCPMarketplaceDialog, MCPServerDialog, ButtonEditor

Update corresponding tests to reflect refactored method signatures.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… factory tests

Three distinct test failures in ./gradlew build are fixed:

1. GPT4AllChatModelFactoryTest (FileSystemException: path too long)
   - Removed BasePlatformTestCase — the test only uses Mockito mocks
     and needs no IntelliJ platform setup
   - Extracted handleProviderNotRunning() in LocalChatModelFactory as a
     protected method (consistent with handleModelFetchError pattern),
     allowing the test to override it without platform context
   - Added doFirst cleanup in build.gradle.kts to delete stale IntelliJ
     temp dirs before each test run (prevents path-depth accumulation)

2. MistralChatModelFactoryTest (apiKey cannot be null or blank)
   - LLMProviderService.providerKeyMap was populated with bound method
     references (stateService::getMistralKey) captured at class-load
     time; ServiceContainerUtil.replaceService had no effect on them
   - Changed to dynamic lambdas so DevoxxGenieStateService.getInstance()
     is resolved on each call, picking up the current mock instance

3. OpenRouterChatModelFactoryTest (MemoryException: maxMessages=0)
   - PostStartupActivity fires during BasePlatformTestCase setup and
     calls ChatMemoryManager.initializeMemory(); mocked state service
     returns 0 for getChatMemorySize() (Mockito default for Integer)
   - Added guard in initializeMemory() to fall back to 10 when the
     configured value is <= 0

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…line

After a long idle period (e.g. Ollama model cold-start > 5 seconds),
a single repaint() is sometimes not enough to wake CEF's rendering
pipeline. A delayed invalidate+revalidate+repaint is now scheduled
150ms after JS execution to guarantee content becomes visible without
requiring user interaction (click/move the panel).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add test coverage for components refactored during SonarLint complexity
reduction, including:
- FindDefinitionToolExecutorTest (PSI tool)
- CppProjectScannerExtensionTest, GoProjectScannerExtensionTest,
  JavaScriptProjectScannerExtensionTest, KotlinProjectScannerExtensionTest
- CachedProjectScannerTest
- MCPToolsManagerTest
- FileSelectionPanelFactoryTest
- LLMProvidersConfigurableTest
- MCPMarketplaceDialogFilterTest, MCPServerDialogEnvVarTest

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Mirrors the backlog workflow guidance from CLAUDE.md so that Gemini-based
AI assistants also understand how to use the Backlog.md MCP for task and
project management activities in this repo.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Archive 129 completed SonarLint cognitive-complexity tasks (S3776, S1602,
S6204, S6205, S1192, S1141) that were resolved during the sonarlint-fixes
refactoring sessions. Also track the empty backlog/tasks directory.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@stephanj stephanj merged commit 33d7e9a into master Feb 21, 2026
7 of 9 checks passed
@stephanj stephanj deleted the sonarlint-fixes branch February 21, 2026 14:48
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