Skip to content

feat: implement $/snyk.configuration notification handler [IDE-1652]#373

Open
nick-y-snyk wants to merge 8 commits intomainfrom
feat/IDE-1652
Open

feat: implement $/snyk.configuration notification handler [IDE-1652]#373
nick-y-snyk wants to merge 8 commits intomainfrom
feat/IDE-1652

Conversation

@nick-y-snyk
Copy link
Copy Markdown
Contributor

Summary

  • Implement $/snyk.configuration JSON-RPC notification handler for centralized enterprise policy enforcement, replacing the typed FolderConfig/$/snyk.folderConfigs infrastructure with a generic Map<String, ConfigSetting> settings system
  • Add durable persistence for global settings, in-memory storage for per-folder configs, change tracking via explicitChanges set, and outbound workspace/didChangeConfiguration using LspConfigurationParam format
  • Migrate all consumers (HTMLSettingsPreferencePage, NativeProjectPropertyPage, ReferenceChooserDialog, SnykToolView, LsConfigurationUpdater) to the new FolderConfigSettings service
  • Remove old infrastructure (FolderConfig, FolderConfigsParam, FolderConfigs, Settings, $/snyk.folderConfigs handler) and bump LS protocol version to 25

What this enables

Enterprise administrators configure security policies via LDX-Sync at tenant/org/machine scope. The Language Server resolves effective settings (applying precedence rules) and pushes them to the Eclipse plugin via $/snyk.configuration. The plugin persists settings durably, tracks user overrides, and sends changes back via workspace/didChangeConfiguration. This aligns Eclipse with the IntelliJ implementation for cross-IDE configuration parity.

Key design decisions

  • Generic map-based settings (Map<String, ConfigSetting>) instead of typed fields — any future LS setting works without Eclipse-side code changes
  • Flag-at-modification change tracking — no baseline diffing; user changes are marked immediately via markExplicitlyChanged()
  • Full-state outbound — every didChangeConfiguration sends all settings with changed flags, not deltas
  • Folder configs are in-memory only — LS is source of truth and re-sends on reconnect
  • Lock metadata stored but not yet enforced in UIisLocked, source, originScope are persisted for a follow-up iteration

Changes

New files

  • ConfigSetting.java — per-setting value with lock metadata and outbound() factory
  • LspFolderConfig.java — per-folder config with immutable withSetting() builder
  • LspConfigurationParam.java — top-level notification/outbound payload type
  • FolderConfigSettings.java — singleton service replacing FolderConfigs with thread-safe storage, typed convenience methods, and atomic computeFolderConfig()
  • LsSettingsKeys.java / LsFolderSettingsKeys.java — LS protocol key constants

Modified files

  • SnykExtendedLanguageClient.java — added snykConfiguration() handler, removed old folderConfig() handler
  • LsConfigurationUpdater.java — replaced getCurrentSettings() with buildConfigurationParam()
  • Preferences.java — added explicitChanges tracking (mark/is/clear, persisted)
  • LsBinaries.javaREQUIRED_LS_PROTOCOL_VERSION bumped from "23" to "25"
  • All consumer classes migrated to FolderConfigSettings

Deleted files

  • FolderConfig.java, FolderConfigsParam.java, FolderConfigs.java, Settings.java, FolderConfigTest.java

Test plan

  • 60 new unit tests added (245 total, all passing, zero regressions)
  • Type deserialization: Gson round-trip for all new types including null fields, various value types, snake_case mapping
  • Notification handler: all payload combinations (global-only, folder-only, both, empty), state reconciliation, scanning mode conversion, exception safety
  • Change tracking: explicitChanges persistence across restart, mark/is/clear operations, multi-key support
  • Outbound payload: LspConfigurationParam structure, changed flags from explicitChanges, no lock metadata in outbound, full-state semantics, reset-to-default (value: null, changed: true)
  • FolderConfigSettings: singleton, path normalization, typed convenience methods, computeFolderConfig atomicity, isConfigured, updateFolderConfig
  • Consumer migration verified via grep: zero remaining references to old types in production code
  • PMD static analysis passes

…nfig management [IDE-1652]

Implement Story 1.1: Configuration reception, storage, and persistence.
Adds new message types (ConfigSetting, LspFolderConfig, LspConfigurationParam),
FolderConfigSettings singleton for thread-safe folder config storage, and
snykConfiguration handler on SnykExtendedLanguageClient that persists global
settings and manages folder configs from the Language Server.
…[IDE-1652]

- Add explicitChanges tracking to Preferences (mark/check/clear/persist with flush)
- Refactor LsConfigurationUpdater to produce LspConfigurationParam instead of old Settings type
- Add ConfigSetting.outbound() factory for value+changed only outbound settings
- Update SnykLanguageServer.getInitializationOptions() to use buildConfigurationParam()
- Add convertInboundValue() for scanning mode format conversion
- Synchronize FolderConfigSettings.setInstance(), add null guards on explicit-change methods
- Extract 21 LS setting key constants to LsSettingsKeys
- Add 21 new tests covering change tracking, payload construction, and round-trip semantics
… getCurrentSettings [IDE-1652]

Migrate HTMLSettingsPreferencePage, NativeProjectPropertyPage, ReferenceChooserDialog,
and SnykToolView from old FolderConfigs/FolderConfig to FolderConfigSettings/LspFolderConfig.
Add bridge in folderConfig() to populate both old and new config systems during transition.
Remove unused getCurrentSettings() from LsConfigurationUpdater and its test.
…v25 [IDE-1652]

Delete FolderConfig, FolderConfigsParam, FolderConfigs, and Settings classes.
Remove old $/snyk.folderConfigs handler and SNYK_FOLDER_CONFIG constant.
Bump REQUIRED_LS_PROTOCOL_VERSION from 23 to 25.
Resolve review findings: token changed flag uses isExplicitlyChanged,
atomic computeFolderConfig for consumer writes, additionalParameters
returns List<String>, folderPath set on empty configs.
@nick-y-snyk nick-y-snyk requested review from a team as code owners March 30, 2026 13:43
@snyk-io
Copy link
Copy Markdown

snyk-io bot commented Mar 30, 2026

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues
Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@snyk-pr-review-bot

This comment has been minimized.

…aths [IDE-1652]

Replace prefs.store() with prefs.storeAndTrackChange() in all user-facing
settings pages (HTMLSettingsPreferencePage, PreferencesPage, BaseHandler,
SnykWizard, SummaryBrowserHandler) so that user edits are tracked as
explicitly changed. Wire folder-scope consumers to use
withSettingIfChanged instead of withSetting. Update LsConfigurationUpdater
to propagate isExplicitlyChanged for all user-changeable settings in the
outbound payload. Remove unused PREF_TO_LS_KEY field.
@snyk-pr-review-bot

This comment has been minimized.


private static FolderConfigSettings instance;

private final ConcurrentHashMap<String, LspFolderConfig> configs = new ConcurrentHashMap<>();

Check warning

Code scanning / PMD

Avoid using implementation types like 'ConcurrentHashMap'; use the interface instead Warning

Avoid using implementation types like 'ConcurrentHashMap'; use the interface instead
for (LspFolderConfig config : folderConfigs) {
try {
addFolderConfig(config);
} catch (Exception e) {

Check warning

Code scanning / PMD

Avoid catching Exception in try-catch block Warning

Avoid catching Exception in try-catch block
@snyk-pr-review-bot

This comment has been minimized.

…user overrides [IDE-1652]

storeAndTrackChange compared against hardcoded empty string default
instead of the registered store default, causing settings with non-empty
defaults to be falsely marked as user-overridden on first save.

HTML settings form now handles null values from LS as reset signals,
calling clearExplicitlyChanged to remove the user override before the
next didChangeConfiguration is sent to the LS.
@snyk-pr-review-bot

This comment has been minimized.

Use Map interface instead of ConcurrentHashMap for field declaration.
Narrow catch clause from Exception to IllegalArgumentException.
@snyk-pr-review-bot
Copy link
Copy Markdown

PR Reviewer Guide 🔍

🧪 PR contains tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Blind Override of User Preferences 🟠 [major]

The applyFormValue method clears the 'explicitly changed' flag whenever a value is null. Since IdeConfigData is a record, Jackson will set fields to null if they are missing from the incoming JSON payload (e.g., if the LS-served HTML form is from a different version or only sends a partial update). This causes the plugin to silently lose user overrides for any field not explicitly present in the HTML form's POST data.

prefs.clearExplicitlyChanged(key);
Brittle Path Normalization 🟠 [major]

The normalizePath method uses toAbsolutePath(), which resolves relative paths against the process's current working directory (user.dir). If the Language Server and the Plugin have different working directories or use different path representations (e.g. symlinks on macOS like /var vs /private/var), the string-based keys in the configs Map will mismatch, causing project-specific settings to fail to apply.

return Paths.get(path).normalize().toAbsolutePath().toString();
Manual Tracking Sync Risk 🟡 [minor]

The performOk method relies on a hardcoded trackedKeys array to detect user changes. If a new preference is added to createFieldEditors but the developer forgets to add it to this array, manual changes to that setting will never be marked as 'explicit' and consequently will never be synchronized back to the Language Server via didChangeConfiguration.

String[] trackedKeys = {
	Preferences.ENDPOINT_KEY, Preferences.INSECURE_KEY, Preferences.AUTHENTICATION_METHOD,
	Preferences.ACTIVATE_SNYK_OPEN_SOURCE, Preferences.ACTIVATE_SNYK_CODE_SECURITY,
	Preferences.ACTIVATE_SNYK_IAC, Preferences.SCANNING_MODE_AUTOMATIC,
	Preferences.ORGANIZATION_KEY, Preferences.ADDITIONAL_PARAMETERS,
	Preferences.ADDITIONAL_ENVIRONMENT, Preferences.PATH_KEY,
	Preferences.MANAGE_BINARIES_AUTOMATICALLY, Preferences.CLI_BASE_URL,
	Preferences.CLI_PATH, Preferences.RELEASE_CHANNEL,
	Preferences.SEND_ERROR_REPORTS, Preferences.ENABLE_TELEMETRY,
	Preferences.TRUSTED_FOLDERS
};
📚 Repository Context Analyzed

This review considered 154 relevant code sections from 11 files (average relevance: 0.97)

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.

2 participants