feat(config): centralized configuration [IDE-1786]#1162
feat(config): centralized configuration [IDE-1786]#1162bastiandoetsch wants to merge 108 commits intomainfrom
Conversation
… [IDE-1786] Phase 2.2 of folder config refactoring: wire snyk-ls to use GAF ConfigResolver with prefix-key-based configuration. New files: - RegisterAllConfigurations: 31 settings with pflag annotations - MigrateSettingsToLocalFields: convert legacy Settings to LocalConfigField - ConfigResolver GAF delegation tests (FC-046 through FC-058) Key changes: - ConfigResolver delegates to GAF ConfigResolver when wired - SetGlobalSettings stores reference; SyncGlobalSettingsToConfiguration writes reconciled values after Config is updated - FolderConfig dual-writes UserOverrides to GAF prefix keys - LDX-Sync adapter dual-writes remote config to GAF prefix keys - clearLockedOverridesFromFolderConfigs clears GAF UserFolderKey - batchClearOrgScopedOverridesOnGlobalChange uses ModifyStoredConfig for atomic read-modify-write with mutex protection - processSingleLspFolderConfig sets fc.conf for dual-write - IsSnykSecretsEnabledForFolder delegates to isSettingEnabledForFolder - Compile-time ConfigResolverInterface satisfaction check - Remove enforced precedence from resolution (locked + regular only) - cmp.Equal uses cmpopts.IgnoreUnexported for FolderConfig
Replace builder.WriteString(fmt.Sprintf(...)) with fmt.Fprintf(&builder, ...) as suggested by golangci-lint.
|
/describe |
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
…nners [IDE-1786] Phase 2.3 of folder config refactoring: inject ConfigResolver into scanner context via enrichContextAndLogger, and migrate all four scanners (OSS, Code, IaC, Secrets) to read ConfigResolver from context with fallback to struct field. - Add DepConfigResolver constant and context helpers (ConfigResolverFromContext, NewContextWithConfigResolver) in internal/context - Inject ConfigResolver into deps map in DelegatingConcurrentScanner - Add getConfigResolver(ctx) helper to each scanner with context-first fallback - Generate ConfigResolverInterface mock via gomock - Tests FC-060 through FC-068 cover injection, retrieval, and fallback paths
…786] Replace NullableField with *LocalConfigField in LSP wire protocol. Unify $/snyk.folderConfigs into $/snyk.configuration using map-based ConfigSetting for both global and per-folder settings. Refactor ConfigResolver to delegate to GAF resolver for all settings except folder metadata (AutoDeterminedOrg, LocalBranches) which are read directly from FolderMetadataKey. Remove legacy fallback paths. Update SyncToConfiguration to correctly write user-settable folder settings to UserFolderKey and LS-enriched metadata to FolderMetadataKey. Migrate scanners (base_scan, pre_scan_command, cli_scanner) to use ConfigResolver for all configurable values instead of direct struct field access.
…ve migration code [IDE-1786] - Move SastSettings from FolderConfig struct to GAF configuration with Get/SetSastSettings helpers - Replace hardcoded persistence lists with dynamic Set+PersistInStorage via SetFolderUserSetting and SetFolderMetadataSetting helpers - Remove all legacy migration code: legacyFolderConfigJSON, legacyStoredConfig, MigrateLegacyFolderConfig, RegisterFolderPersistence, getStoredConfigForMigration, MigrateFolderConfigOrgSettings, OrgMigratedFromGlobalConfig flag, settings_migration.go - Fix updateFolderOrgIfNeeded: check orgSettingsChanged before global org inheritance to prevent overwriting explicit user org changes - Rename tests and comments to remove stale migration references - Add precedence and scanner precedence smoke tests - Add config resolver delegation tests
Move cliPath, Insecure, AdditionalOssParameters, and ReleaseChannel fields from CliSettings struct directly into Config. Promote all CliSettings methods (Installed, IsPathDefined, Path, SetPath, DefaultBinaryInstallPath) to Config methods with Cli prefix. Remove CliSettings struct, NewCliSettings constructor, CliSettings() accessor, SetCliSettings() mutator, and the dedicated cliPathAccessMutex (Config's existing mutex provides thread safety). Update all ~80 call sites across 30 files from c.CliSettings().X() to c.X() pattern.
|
/describe |
Document the complete configuration architecture including: - Configuration scopes (machine, org, folder) with prefix key storage - Flag registration via pflag.FlagSet with annotations - Precedence resolution rules per scope (locked > user > remote > default) - Effective organization resolution flow - LDX-Sync remote configuration with 4 sync triggers - Locked field enforcement (sync-time clearing + edit-time rejection) - IDE ↔ LS protocol with ConfigSetting wire type - FolderConfig thin wrapper architecture - Persistence via SetFolderUserSetting/SetFolderMetadataSetting helpers Include mermaid sequence diagrams for all major flows: - Machine and org scope precedence resolution - Effective org determination - LDX-Sync trigger lifecycle - Locked field enforcement - IDE→LS and LS→IDE configuration exchange
…n [IDE-1786] Migrate boolean, string, and integer Config struct fields to use GAF Configuration as the backing store via UserGlobalKey prefix keys. Config getters/setters now delegate to gafGetBool/gafGetString/gafGetInt helpers, removing the need for struct fields and mutex locking (GAF is thread-safe). Key changes: - Add gafConf/gafGetBool/gafSetBool/gafGetString/gafSetString/gafGetInt/gafSetInt helper methods on Config for type-safe GAF access - Register flags via RegisterAllConfigurations in newConfig() so defaults are available immediately after engine init - Migrate 16 boolean fields (product toggles, feature flags, proxy settings) - Migrate 6 string fields (cliBaseDownloadURL, proxy*, authenticationMethod, etc.) - Migrate 2 integer fields (hoverVerbosity, riskScoreThreshold) - Skip Phase 1 raw writes in processConfigSettings for migrated settings (apply functions write validated values via setters) - Update SetUpEngineMock to copy GAF settings when replacing engine - Replace MockConfiguration with real configuration.NewWithOpts() in tests for simpler, more robust test setup
…ated settings [IDE-1786] Now that boolean and int settings are backed by GAF UserGlobalKey, the ConfigResolver's fallback to ConfigProvider methods is redundant. GetValue already resolves through the full prefix key chain including UserGlobalKey defaults. Key changes: - Shrink ConfigProvider interface to only FilterSeverity + IssueViewOptions (composite types still on Config struct) - Replace isSettingEnabledForFolder(fallback) with GetBool delegation - Remove r.c nil guards from methods that no longer access ConfigProvider - Add DefaultConfigResolver test helper with proper prefix key wiring - Register pflag flags in SetUpEngineMock so GAF ConfigResolver has scope metadata for resolution - Update all defaultResolver functions in tests to use proper wiring - Replace MockConfiguration with real configuration.NewWithOpts() in tests
|
/review |
…age ordering, clean up dead code [IDE-1786]
- Define 27 new Setting* constants for all internal configuration keys
(device_id, offline, format, trusted_folders, etc.) in ldx_sync_config.go
- Replace all raw strings in UserGlobalKey("...") calls across 50+ files
with the corresponding types.Setting* constants
- Fix PersistInStorage ordering: must be called BEFORE Set, not after,
in all folder config write paths (5 files)
- Remove stale ConfigProvider mock expectations (FilterSeverity,
IssueViewOptions) after interface was emptied
- Remove dead StoredConfig struct, FolderConfigsParam, and related
serialization code from xdg.go
- Remove 125+ thin getter/setter wrapper methods from Config struct
- Extract 9 business logic methods into standalone package-level functions
- Increase test timeout from 45m to 60m for smoke test suite
|
/describe |
…ckFileName, add engine/conf context helpers [IDE-1786] Phase 3.5 completion: - Inline SetConfigFile into main.go and ls_extension/main.go, remove method - Extract SetOrganization to standalone function, update ~35 callers across 17 files - Inline CLIDownloadLockFileName instance method, update 6 callers to use standalone Phase 3.6.1: - Add Engine and Configuration context helpers to internal/context (NewContextWithEngine/EngineFromContext, NewContextWithConfiguration/ConfigurationFromContext) - Add DepEngine and DepConfiguration dependency keys - Table-driven tests for all dependency-map context helpers (Workspace, Engine, Configuration)
…te NewConfigResolver signature [IDE-1786] Remove all references to LDXSyncConfigCache from test files across the codebase. Update all NewConfigResolver(cache, logger) calls to NewConfigResolver(logger). Replace cache-based org storage with GAF-native equivalents: - cache.SetOrgConfig -> WriteOrgConfigToConfiguration - cache.SetFolderOrg -> SetAutoDeterminedOrg - cache.GetOrgIdForFolder -> ReadFolderConfigSnapshot.AutoDeterminedOrg Fix Test_processResults_ShouldCountSeverityByProduct: create folder after SetUpEngineMock so f.conf and workspace storage use the same configuration. Update Test_RefreshConfigFromLdxSync_EmptyFolderPath: document that empty paths are skipped by ReadFolderConfigSnapshot (PathKey returns empty string leading to early return).
|
/describe |
… smoke tests [IDE-1786] - Replace time.Sleep with require.Never in oss_test.go for Test_scheduleNewScanWithProductDisabled_NoScanRun and Test_scheduleNewScan_ContextCancelledAfterScanScheduled_NoScanRun - Replace time.Sleep with require.Never in precedence_smoke_test.go for Test_SmokeScanPrecedence_AllDisabled_NoScansRun and Test_SmokeScanPrecedence_UserOverrideDisablesProduct - Use TempDirWithRetry for storage directory in redirectConfigAndDataHome to prevent flaky TempDir cleanup failures when goroutines outlive tests - Call c.SetStorage(s) in redirectConfigAndDataHome so c.Storage() is non-nil, fixing nil pointer panic in NewOAuthProvider during OAuth smoke tests (Test_InvalidExpiredCredentialsSendMessageRequest)
…DE-1786] Phase 3.6.2: Update server.Start signature - Change Start(c *config.Config) -> Start(engine workflow.Engine) - Derive conf from engine.GetConfiguration() inside Start - Derive logger from engine.GetLogger() after ConfigureLogging sets it - Update jrpc2 ServerOptions logger closures to use engine.GetLogger() - Use config.CurrentConfig().ConfigureLogging(srv) as interim bridge until Phase 3.6.7 extracts token scrubbing from Config - Update main.go and ls_extension/main.go callers to pass c.Engine()
…ow.Engine [IDE-1786] Replace *config.Config parameter with workflow.Engine across multiple packages as part of Phase 3.6.6 of the config refactoring (remove LDXSyncConfigCache). Changes include: - infrastructure/code: migrate code_html.go, sarif_utils.go, ai_fix_handler.go, sast_local_engine.go, snyk_code_http_client.go, autofix.go, code.go - infrastructure/oss: migrate oss_html.go (NewHtmlRenderer) - infrastructure/secrets: migrate secrets_html.go (NewHtmlRenderer) - domain/ide/command: replace config.CurrentConfig() with cmd.engine in code_fix_apply_edit.go, code_fix_diffs.go, code_fix_feedback.go, navigate_to_range.go, generate_issue_description.go and all other command files - application/server/configuration.go: thread engine through updateFolderOrgIfNeeded - Update all callers and test files to pass engine/configuration instead of *config.Config
…ndant calls [IDE-1786] Introduce types.GetGlobalOrganization(conf) to enforce correct precedence (UserGlobalKey first, then configuration.ORGANIZATION fallback), replacing 16 direct conf.GetString(configuration.ORGANIZATION) reads across 9 files. Add types.SettingConfigFileLegacy constant to replace magic "configfile" string in main.go, ls_extension/main.go, and config.go. Eliminate redundant engine.GetConfiguration()/GetLogger() calls in ~27 locations by caching conf and logger at function entry and passing to helpers.
Create types.TokenService interface and TokenServiceImpl to encapsulate token lifecycle: writing to GAF configuration, adding scrub terms to the logger, and notifying change listeners. Update NewAuthenticationService and NewDelegatingScanner constructors to accept TokenService as a dependency. Auth service uses tokenService.SetToken() directly instead of config.SetToken(), and scanner uses tokenService.TokenChangesChannel() instead of config.TokenChangesChannel(). Config.SetToken/TokenChangesChannel now delegate to the internal TokenService; these will be removed when Config struct is deleted (3.6.8).
…alone functions [IDE-1786] Create SetupLogging(engine, tokenService, server) as standalone replacement for Config.ConfigureLogging(). Manage log file and scrubbing writer as package-level state instead of Config fields. Add types.IsDefaultEnvReady(conf) and types.WaitForDefaultEnv(ctx, conf) backed by a channel stored in GAF configuration under SettingDefaultEnvReadyChannel. Replace config.CurrentConfig().IsDefaultEnvReady() call in configuration.go with the standalone function. Add DisableFileLogging(conf, logger) as standalone replacement for Config.DisableLoggingToFile(). Remove unused logFile field from Config.
Add auth method selector, dirty-state tracking, auth field monitor, and updated config HTML template with full settings page JS stack.
Consolidate JS tests under js-tests/ with ESLint-based ES5 checking and node --test auto-discovery. Remove old js-tests from treeview template.
Update Makefile JS test targets, .gitignore, and goreleaser config for the new js-tests layout and ES5 ESLint check.
…configuration.go Replace duplicate logic in applyApiEndpoints and applyAuthenticationMethod with the shared helpers from apply_auth_config.go. Also removes the redundant ConfigureProviders call after Logout in the endpoint-change path.
…g to scan all JS
- Add space before ( in anonymous function declarations in dirty-tracker.js
- Move eslint.config.js to repo root so base path covers all template JS files
- Run eslint on .. to scan whole repo instead of only js-tests directory
- Exclude Go template files with ${} placeholders that can't be parsed, ESM
test files, and minified vendor polyfills from ES5 linting
- Execute now returns an error for any arg count other than 0 or 3 - Replace time.Sleep with firstStarted channel in CancellationPreservesExistingToken test - Add missing second Authenticate call to actually trigger cancellation in the test - Add clarifying comments to login_test.go tests explaining argument intent
…ation Move change listener notification out of checkDirty() so that DOM mutations (e.g. auth-field-monitor clearing the token field) happen before the dirty comparison, eliminating the double collectDataFn() call and the split-reality between the passed data snapshot and the live DOM within the notification loop. - Add DirtyTracker.runChangeListeners(): collects current form data and notifies all registered listeners; callers invoke this before checkDirty() so side-effects settle first. - Simplify checkDirty() to a single collect-and-compare with no listener notification. - Update triggerChangeHandlers() in form-state.js to call runChangeListeners() then checkDirty() in sequence. - Fix reset-handler.js: was referencing window.ConfigApp.dirtyTracker (always undefined) instead of window.dirtyTracker; both reset paths now correctly call runChangeListeners() + checkDirty(). - Update dirty-tracker tests: rename listener tests to target runChangeListeners(), add assertion that checkDirty() does not invoke listeners. [IDE-1701]
…progress ConfigureProviders (called in applyAuthConfig) acquires the auth mutex, but a blocking Authenticate holds that same mutex while waiting for an OAuth callback. Without cancelling the in-progress auth first, calling ConfigureProviders deadlocks because Authenticate (which would cancel the old auth) never runs. - Add CancelOngoingAuth() to AuthenticationService interface and implement it: cancels the in-progress auth context without acquiring the auth mutex. - Call CancelOngoingAuth() in loginCommand.Execute before applyAuthConfig, so the blocking Authenticate releases the mutex before ConfigureProviders tries to acquire it. - Use CancelOngoingAuth() inside Authenticate itself to deduplicate the cancel-previous logic. - Add BlockingFakeAuthProvider test double and regression test that deadlocks without the fix.
…n [IDE-1701] Remove fallback to AUTHENTICATION_TOKEN and OAuth token keys when the structured user-global token is not set, matching WriteTokenToConfig as the single source for GetToken. Made-with: Cursor
rrama
left a comment
There was a problem hiding this comment.
Submitting my comments so far. I am still a long way off, but I want to at least feedback some of the bugs I spotted.
Concern:
- To me it was not immediately clear that there is special folder config paths for
OrgSetByUser,PreferredOrg, andAutoDeterminedOrgthat do not have wiring, but all other folder configs need it. I am wondering if we should switch to calling them something else to make it clearer. They could beFolderOrgSelectorsor something (not so keen on calling them "native"), then if those functions are renamed to follow suit it would be clear if you are getting wiring for full or not. Then could do similar for the Git enrichments (not so keen on calling them "metadata"). - You have to know a lot about a key to get its value, it would be easier if all the information about a setting and how to get it's value was all in one place and you just use that everywhere. Currently it is spread between files like
configuration.go,config.go,config_readers.go,ldx_sync_config.goandregister_configurations.go, so there is a bit of jumping back and forth to figure out that some user global keys are overridden by LDX-Sync, etc., but feels weird I have to know it is a user global key in some of the places instead of that being stored with the key definition.
Testing improvements:
- Maybe an additional test to test a bit further / more multi-step than just
Test_RefreshConfigFromLdxSync_PreservesNonLockedOverrides: A test which starts off with user set at folder risk score at200, then a remote admin locks it to300and user fetches, then the remote admin unlocks and unsets the setting plus the user fetches, then verify that we get back the default of0and not the stale200.
Personal things to still check:
- Do we need migration code?
- Look into the bug AI thought it found:
Tracing ApplyLspUpdate (IDE → LS folder config writes)
FolderConfig.ApplyLspUpdate (folder_config.go:255) → applyFolderScopeUpdates (:344):applyBasicFolderFields (:395): Handles SettingBaseBranch, SettingReferenceBranch, SettingLocalBranches, SettingAdditionalParameters, SettingAdditionalEnvironment, SettingReferenceFolder, SettingScanCommandConfig. All written to UserFolderKey as *LocalConfigField{Value, Changed:true} except SettingLocalBranches which goes to FolderMetadataKey.
applyPreferredOrg (:488): Sets both SettingPreferredOrg and SettingOrgSetByUser together via UserFolderKey. Marks both as handled.
applyOrgSetByUser (:520): Handles standalone SettingOrgSetByUser changes. Note: applyPreferredOrg already marks SettingOrgSetByUser as handled at line 490, but applyOrgSetByUser re-adds it at line 521 — this is fine since the handled map is only used by the generic PATCH loop.
Generic PATCH loop (:373-391): For any remaining folder-scoped settings not in handled, applies Changed:true values to UserFolderKey, or Unsets on Value:nil.
Issue: getSettingValue doesn't check Changed flag
getSettingValue (folder_config.go:264-276) does not check cs.Changed. This means applyBasicFolderFields and applyPreferredOrg will process settings even when Changed: false. The generic PATCH loop at line 374 correctly checks !cs.Changed, but the explicit handlers don't. This is inconsistent with the documented PATCH semantics. In practice, it's mitigated by equality checks (e.g., baseBranch != cur), but a setting sent with Changed:false and a different value than current would still be applied.
| - Folder Config Notification | ||
| - method: `$/snyk.folderConfigs` | ||
| - params: `types.FolderConfigsParam` | ||
| - Configuration Notification (protocol v25+) |
There was a problem hiding this comment.
Nitpick: Don't state the protocol version, if someone wants historic analysis, they can get it from the Git history.
| * limitations under the License. | ||
| */ | ||
|
|
||
| package types |
There was a problem hiding this comment.
Why is this whole file in the types package?
| // goroutine. SetEngineDefaults only sets defaults when the key is not yet present, | ||
| // so a pre-seeded configuration ensures the goroutine reads the test-specific paths | ||
| // rather than the system defaults (which in CI can include many unrelated Java installs). | ||
| conf := configuration.NewWithOpts(configuration.WithAutomaticEnv()) |
There was a problem hiding this comment.
Minor nitpick: Comment should also explain we use this technique to be more realistic, as in prod we have WithAutomaticEnv().
| func initEngineForClientSettingsTest(t *testing.T) workflow.Engine { | ||
| t.Helper() | ||
| e, _ := InitEngine(nil) | ||
| e.GetConfiguration().Set(configresolver.UserGlobalKey(types.SettingBinarySearchPaths), []string{}) |
| func initEngineForConfigTest(t *testing.T) (workflow.Engine, *TokenServiceImpl) { | ||
| t.Helper() | ||
| engine, ts := InitEngine(nil) | ||
| engine.GetConfiguration().Set(configresolver.UserGlobalKey(types.SettingBinarySearchPaths), []string{}) |
There was a problem hiding this comment.
Same, not meant to be keyed.
| modified := c.enableDeltaFindings != enabled | ||
| c.enableDeltaFindings = enabled | ||
| return modified | ||
| return getCustomEndpointUrlFromSnykApi(types.GetGlobalString(conf, types.SettingApiEndpoint), "deeproxy") |
There was a problem hiding this comment.
Nitpick: Again may be worth calling out in a comment that LDX-Sync will directly override the user global key for API endpoint.
| // AuthenticationMethodMatchesCredentials returns true if the token matches the configured authentication method. | ||
| func AuthenticationMethodMatchesCredentials(token string, method types.AuthenticationMethod, logger *zerolog.Logger) bool { | ||
| if method == types.FakeAuthentication { | ||
| return true // We allow any value for the token in unit tests which use FakeAuthentication. |
There was a problem hiding this comment.
Nitpick: Leave the comment in.
| if org != "" { | ||
| // Store the resolved org so that defaultFuncOrganization's UUID fast-path | ||
| // returns it directly next time, avoiding /rest/self. | ||
| conf.Set(configuration.ORGANIZATION, org) |
There was a problem hiding this comment.
Not needed. After a resolved defaultFunc GAF will cache it.
Although standalone and tests do not have the cache enabled... See https://snyksec.atlassian.net/browse/IDE-1727
So a future enhancement to remove this then.
| c.deviceId = deviceId | ||
| } | ||
| if engine == nil { | ||
| conf := configuration.NewWithOpts(configuration.WithAutomaticEnv()) |
There was a problem hiding this comment.
Future enhancement reminder: We should enable the cache for standalone / tests: See https://snyksec.atlassian.net/browse/IDE-1727
| } | ||
| if v, ok := settingBool(settings, types.SettingIssueViewIgnoredIssues); ok { | ||
| ivo.IgnoredIssues = v | ||
| } |
There was a problem hiding this comment.
If only one is set then the other will be defaulted back to `false. TODO - Check severity filters too.
…-1701] WriteTokenToConfig was falling back to AUTHENTICATION_TOKEN and CONFIG_KEY_OAUTH_TOKEN when SettingToken was not set, while GetToken only reads from SettingToken. This mismatch caused spurious token-change notifications when the fallback keys held a value (e.g. from environment), breaking Test_TokenChangedToSameToken_ChannelsNotInformed. Also removes redundant handleProviderInconsistencies call in authenticate() since the provider is already checked immediately after.
…701] Update GAF to v0.0.0-20260331101019-870612009636 which includes the fix for math.MaxInt64 overflow on 32-bit targets (linux_386, windows_386) in the conversion package.
Add linux_386 and windows_386 binaries to the upload script to match the goreleaser build targets. Without this, the SHA256SUMS verification fails because it includes checksums for 386 binaries that were never copied to the verification directory.
When logout is called before any provider has been selected (e.g. during endpoint change triggered logout), authProvider is nil and ClearAuthentication panics. Add a nil check before calling it.
…-1701-rebased-onto-IDE-1786
feat(IDE-1701): add auth params to login command and fix auth mutex [rebased onto IDE-1786]
# Conflicts: # application/codeaction/codeaction.go # application/config/config.go # application/server/configuration.go # application/server/server_smoke_test.go # application/server/server_test.go # domain/ide/command/execute_cli.go # domain/ide/workspace/folder.go # domain/scanstates/scan_state_aggregator.go # domain/scanstates/scan_state_aggregator_test.go # domain/scanstates/summary_html.go # domain/snyk/scanner/scanner.go # domain/snyk/scanner/scanner_test.go # domain/snyk/scanner/test_scanner.go # go.mod # go.sum # infrastructure/code/snyk_code_http_client.go # infrastructure/oss/cli_scanner.go # infrastructure/secrets/secrets.go # infrastructure/secrets/secrets_test.go # internal/folderconfig/folder_config.go # internal/types/config_resolver.go # internal/types/mock_types/scan_mock.go # internal/types/scan.go
chore: merge main into 1162
| key := configresolver.FolderMetadataKey(dst, name) | ||
| conf.PersistInStorage(key) | ||
| conf.Set(key, v) | ||
| } |
There was a problem hiding this comment.
why would we need to persist config for base scan ?
| for _, name := range userSettings { | ||
| if v := conf.Get(configresolver.UserFolderKey(src, name)); v != nil { | ||
| key := configresolver.UserFolderKey(dst, name) | ||
| conf.PersistInStorage(key) |
There was a problem hiding this comment.
Persist is now being called in many places, it should be centralized, it can be done on init and maybe when a folder is trusted
| userSettings := []string{ | ||
| SettingBaseBranch, SettingReferenceBranch, SettingAdditionalParameters, | ||
| SettingAdditionalEnvironment, SettingReferenceFolder, SettingScanCommandConfig, | ||
| SettingPreferredOrg, SettingOrgSetByUser, | ||
| } |
There was a problem hiding this comment.
we shouldn't do this, instead load config names via scope and iterate through them
| gafConfiguration := conf | ||
|
|
||
| fs := pflag.NewFlagSet("snyk-ls-config", pflag.ContinueOnError) | ||
| types.RegisterAllConfigurations(fs) |
There was a problem hiding this comment.
this is also called when we create a new config so it's duplicated.
| logger.Debug().Err(err).Str("method", "clientSettingsFromEnv").Msgf("couldn't parse oss config %s", oss) | ||
| } | ||
| c.SetSnykOssEnabled(parseBool) | ||
| conf.Set(configresolver.UserGlobalKey(types.SettingSnykOssEnabled), parseBool) |
There was a problem hiding this comment.
The API to set a config is very confusing, when setting a configuration we must know the the scope which is pretty much error prone.
Instead we should simply just call Set and it will determine what the scope of this setting is based on what we already registered.
User description
Summary
Phase 2 of the IDE-1786 configuration resolution refactor:
ConfigResolverto read settings from GAF prefix keys instead of struct fields. InjectConfigResolverinto context for scanner access.map[string]*ConfigSettingfor LSP configuration exchange. AddLspFolderConfigwith per-folder settings maps.SastSettingsfromFolderConfigstruct field to GAF configuration withGet/SetSastSettingshelpers.persistedUserFolderSettings,persistedFolderMetadataSettings) andRegisterFolderPersistence()withSetFolderUserSetting/SetFolderMetadataSettinghelpers that combineSet+PersistInStorage.legacyFolderConfigJSON,MigrateLegacyFolderConfig,MigrateFolderConfigOrgSettings,OrgMigratedFromGlobalConfig,settings_migration.go).CliSettingsstruct intoConfig, promoting all fields and methods directly. Remove back-pointer pattern and separate mutex.precedence_smoke_test.goandscanner_precedence_test.gofor config resolution precedence validation.Test plan
make lint— 0 issuesmake test— all unit tests passSMOKE_TESTS=1 make test— smoke tests pass (except pre-existingTest_InvalidExpiredCredentialsSendMessageRequestflake)INTEG_TESTS=1 make test— integration testsPR Type
Enhancement, Refactor
Description
Diagram Walkthrough
flowchart LR subgraph Previous System C["config.Config"] end subgraph New System GAF_Conf["configuration.Configuration (GAF)"] CR["ConfigResolver (types)"] LS["LS Core Services<br/>(codeaction, scanner, etc.)"] NewInterface["New Config Accessors"] end C -->|Data Loaded Into| GAF_Conf GAF_Conf -->|Resolution Logic| CR CR -->|Provides Unified Access| LS LS -->|Uses| NewInterface C -->|Removed| Deprecated ``` <details> <summary><h3> File Walkthrough</h3></summary> <table><thead><tr><th></th><th align="left">Relevant files</th></tr></thead><tbody><tr><td><strong>Additional files</strong></td><td><details><summary>101 files</summary><table> <tr> <td><strong>mcp.json</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-19eb5f2245594c429cc37560d082721fbabff68227984d8d40bad80fd3514b83">[link]</a> </td> </tr> <tr> <td><strong>coder.md</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-b89595e8329168380c8d0d806f10fe48e0c74d6480bdd36d5f52fb50e60b38e7">+112/-0</a> </td> </tr> <tr> <td><strong>planner.md</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-3da7d9f10c1d522c26d34593af5559179e560e5f132e48d11925d54bc7e3ae8c">+95/-0</a> </td> </tr> <tr> <td><strong>qa.md</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-4399ee622fcd198ee75d7ce0c8f8bf764146afab8534c4b73be17d1b0d2e83c4">+126/-0</a> </td> </tr> <tr> <td><strong>commit.md</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-8a7812887cf57f02817a41095c0bc96e39f12a86dcedc8b9c7717843fb9fecff">+217/-0</a> </td> </tr> <tr> <td><strong>create-implementation-plan.md</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-c1589a6ef920a2e344d943924041069ef37a00f0c35b10b665b908aa4c3fe12e">+126/-0</a> </td> </tr> <tr> <td><strong>implementation.md</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-b7db59ef37d8544cde3bd3cb4463d2753bbcd1ef3da3e4d743d6d469476ab938">+202/-0</a> </td> </tr> <tr> <td><strong>verification.md</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-e63ba9b85e4f0149745953751025c71f5b9b3afd6dfa43b55ece2d3b0bfa56e7">+270/-0</a> </td> </tr> <tr> <td><strong>upload-to-s3.sh</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-4ec24b2c614b7504e801da062ef7c0a0ea927a853af71949117f9be1416955bd">+0/-12</a> </td> </tr> <tr> <td><strong>.goreleaser.yaml</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-7326b55c062b0f46fe9e39aace0a25f4515cf206040fb91a6fd2cae839f5e826">+1/-4</a> </td> </tr> <tr> <td><strong>.tmp_ignore</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-3a301d08bc19d4e6a95a86d0f5f652932e70406c818acb7c1497c799dce6d2c7">[link]</a> </td> </tr> <tr> <td><strong>launch.json</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-bd5430ee7c51dc892a67b3f2829d1f5b6d223f0fd48b82322cfd45baf9f5e945">+0/-23</a> </td> </tr> <tr> <td><strong>tasks.json</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-7d76d7533653c23b753fc7ce638cf64bdb5e419927d276af836d3a03fdf1745a">+0/-24</a> </td> </tr> <tr> <td><strong>coder.md</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-54b2c28a8e7b934853b4ab315640e41e7d75915418749972b73660a73dd2b8b6">+71/-0</a> </td> </tr> <tr> <td><strong>planner.md</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-3de3f79204a2442206f81923eaf79f4784cd2a508dde3722261ae346b527b4ba">+70/-0</a> </td> </tr> <tr> <td><strong>qa.md</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-4b3ee0d066f86a40697b5a63f015144677bddd2e4afc190c20f1e5d4316b1dbd">+117/-0</a> </td> </tr> <tr> <td><strong>general.mdc</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-56f646b00fd9a6c0573b57c0974764abd7f601a2deb90984147b1f66f7b4e6af">+112/-0</a> </td> </tr> <tr> <td><strong>SKILL.md</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-3eee1259a01cb01a6e29a2472eefcf3975d16e88e4c4841d7cb954dcedc57bdb">+260/-0</a> </td> </tr> <tr> <td><strong>SKILL.md</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-1e09e3863ee46b9fdc6f65d71c688175b12b8a2e7f4b0a994925ce4f52095352">+116/-0</a> </td> </tr> <tr> <td><strong>SKILL.md</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-773a18b37f68a8d4a8d73eb1a67eb4a70fd56c90d24f00295e36778a199e53b3">+241/-0</a> </td> </tr> <tr> <td><strong>SKILL.md</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-01767e331487ad3b20729c5e0747a8f44b4395e7ffdf7038b2fb8eb622a23e9b">+333/-0</a> </td> </tr> <tr> <td><strong>CLAUDE.md</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-6ebdb617a8104a7756d0cf36578ab01103dc9f07e4dc6feb751296b9c402faf7">+114/-0</a> </td> </tr> <tr> <td><strong>Makefile</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-76ed074a9305c04054cdebb9e9aad2d818052b07091de1f20cad0bbac34ffb52">+2/-2</a> </td> </tr> <tr> <td><strong>README.md</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5">+26/-22</a> </td> </tr> <tr> <td><strong>helpers.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-939d219344d7e0ee2fabad9bd93cf499c569729779d098d7d7da97fefc181d15">+1/-15</a> </td> </tr> <tr> <td><strong>configuration_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-e141faafb3f0507956b85e92ac3b584c7c706bd96e7f428c7ef95d0d8b2df564">+752/-756</a></td> </tr> <tr> <td><strong>ldx_sync_smoke_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-e86bba96f063a23a5407b87f1d43156fbf47ff435cf44fc7324550746bc13305">+134/-61</a></td> </tr> <tr> <td><strong>scan_notifier.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-1b61c83cfc491251abf25e52610132617ca8ea6b0c1d9347b948fde580eaae42">+2/-5</a> </td> </tr> <tr> <td><strong>scan_notifier_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-5fdc92093964521489fec0d3eb3f9384994e19496fc0d274e0d6a3c3086a975d">+32/-24</a> </td> </tr> <tr> <td><strong>notification_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-09b80ca28f0c9f8db60c941c24e92dfc65ded48c06249e70e2004faec30b9891">+26/-25</a> </td> </tr> <tr> <td><strong>parallelization_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-dfb264976fa1c23451dc8d19b018920487af818f524aa24ea49211bd8b6326e9">+30/-24</a> </td> </tr> <tr> <td><strong>precedence_smoke_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-1c743b9b799604d498e5a5290961ffc135dec375c44150ad820cba81f3926d39">+1077/-0</a></td> </tr> <tr> <td><strong>secrets_smoke_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-c1510bd6a7151e3624d073a590787bd9af09d36b87a53a56067ffc0f3c8603fd">+24/-23</a> </td> </tr> <tr> <td><strong>server_smoke_treeview_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-abf8d4beebabcdeea5250f1698dc768bfbd744c22da6c343b552b5ed02908147">+11/-10</a> </td> </tr> <tr> <td><strong>server_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-165bad981a0cc202462a2fea7f236eab9ca3a72bd47fe8bae6b3adad801351fb">+272/-231</a></td> </tr> <tr> <td><strong>trust_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-e429a057cdac11e281a6ee8603bf8a5ab6dfaf0daedaec873982c47b28d7d431">+51/-49</a> </td> </tr> <tr> <td><strong>parser_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-56f8b9f576282024cef366a3d2024e23c393bc424bd1a7af8917142efcf913e0">+4/-4</a> </td> </tr> <tr> <td><strong>configuration.md</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-17ed18489a956f326ec0fe4040850c5bc9261d4631fb42da4c52891d74a59180">+712/-0</a> </td> </tr> <tr> <td><strong>configuration-effective-org.mmd</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-973fec236ae811f6a90a055f6b7d0da65dc4d11596911ce8ad89250223805426">+13/-0</a> </td> </tr> <tr> <td><strong>configuration-ide-to-ls.mmd</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-d96f7a3876e2a3103d4016e855aeed2eaf4e094231824ade00f1d15863ca2117">+29/-0</a> </td> </tr> <tr> <td><strong>configuration-ldx-sync-triggers.mmd</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-df333a4abf24cf3d87db395e0abe48a2faa721094e4c5c85350a3e539f7f5136">+39/-0</a> </td> </tr> <tr> <td><strong>configuration-locked-fields.mmd</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-38952676823280ad4b068d0c895c67c0793a9f12baa5fafbc4272e24b92e2188">+23/-0</a> </td> </tr> <tr> <td><strong>configuration-ls-to-ide.mmd</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-e87e10816f9abd36bfa4484439e3525b9094a79520d362815a983bfedd8f9587">+35/-0</a> </td> </tr> <tr> <td><strong>configuration-precedence-folder.mmd</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-cf55942689f0076c1c0d5e590504f623b7d4a2163177bf6a9c38b5fe2abc61e9">+43/-0</a> </td> </tr> <tr> <td><strong>configuration-precedence-machine.mmd</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-1a8c5dae9ef9700a8d68771cf78fe1053bd3a2b0d08b7dc6392ae9bce67ddcb8">+27/-0</a> </td> </tr> <tr> <td><strong>configuration-precedence-org.mmd</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-45c665222948a0e96307bcec7893b2c2eb30a1940831992d8bd16c015a7dca50">+31/-0</a> </td> </tr> <tr> <td><strong>tree-view.md</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-539534acc1cc1dac4c4790bdca3d442787d7e99ae04349bee000213f08300a28">+2/-2</a> </td> </tr> <tr> <td><strong>ui-rendering.md</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-c5a817d72c0cce20d0ef1e30f346d1533d38bf440472d1a0944fb0ad0c82f98a">+3/-3</a> </td> </tr> <tr> <td><strong>clear_cache_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-f59e398f3890e4a5979f96e46822865c12c0a1c24a04488066e1110e28f217ee">+12/-9</a> </td> </tr> <tr> <td><strong>code_fix_diffs_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-48255cf8a46398666fde50497322859b28c595de794ffd6670ece78b57ae7f75">+5/-7</a> </td> </tr> <tr> <td><strong>code_fix_feedback_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-9ecc2e3d8ac8d287a04858a39ff2b791deda6c161b005159f1df9cd201561be2">+24/-22</a> </td> </tr> <tr> <td><strong>code_fix_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-b6e42c27f7465637e31a6b441bb21a325b705c2e602cc5208182658553a53e71">+28/-18</a> </td> </tr> <tr> <td><strong>command_factory.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-b7c8bb6d3fa17d1b86a8de859670a7d849bdcedceb8d9a27f4e7f1a74b5d340d">+35/-31</a> </td> </tr> <tr> <td><strong>command_service.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-f91e9940ae7491a26a9708f682296ad692d4044fb82fad0d67811bc13f50fa0f">+12/-6</a> </td> </tr> <tr> <td><strong>command_service_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-4e5012d752e62ca48321ab14a65a40b32718552b72d0510af51c9eccfb981154">+4/-3</a> </td> </tr> <tr> <td><strong>configuration_command_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-4e6fcd9606a6e827d54cddeaf143ea61e51516a7e24ebcee13d0968284546bb0">+6/-5</a> </td> </tr> <tr> <td><strong>connectivity_check.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-bd2f39aac9325739fa4bc8f0086a9dbeee25ae8965cfaaebb59ebaf24bfc5892">+6/-7</a> </td> </tr> <tr> <td><strong>connectivity_check_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-d099e6ed42cac1be0e693600339935f0954b0ee310f46436ccb1fcc9b7264c46">+7/-7</a> </td> </tr> <tr> <td><strong>directory_diagnostics.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-c063651ad364c31d1c991853bd8e83c7c7dcde73b16f929e878721e11d1df8a5">+12/-6</a> </td> </tr> <tr> <td><strong>directory_diagnostics_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-cf8506645d2be31c6eb3d3f8ad413863197d6b1793829408240eced9782744cb">+17/-11</a> </td> </tr> <tr> <td><strong>folder_handler.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-85f453996002ebf21ce07aa3db62fcd3d18a1861f517804721583decb421a90d">+103/-199</a></td> </tr> <tr> <td><strong>folder_handler_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-657ad7fa06e97a16b4e8eb7cddc64cd5e53343e6513ef874563e83ffd694416b">+181/-344</a></td> </tr> <tr> <td><strong>generate_issue_description.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-20aaf0cdc220b7a600d894877440f647f93c34bbc4e4f023e33422b4f2e77ccf">+17/-15</a> </td> </tr> <tr> <td><strong>get_active_user_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-c5b8060a5d409b868500ca069b1916a9a35584924e1e61be677148d12a44064d">+18/-16</a> </td> </tr> <tr> <td><strong>get_feature_flag_status_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-29de3939a8441248dd44aa2f2eb09f23a57909cf126d85840d0a1519580e25f3">+11/-6</a> </td> </tr> <tr> <td><strong>get_tree_view_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-443abf9c8f12ff271e64a1eed61e5ddc426eca805d6d5be05cffab1a0e176166">+6/-6</a> </td> </tr> <tr> <td><strong>ignores_integration_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-79ebbec5beb7c426863a36683370db366beb6d364890c7e7155c4a8936527277">+25/-31</a> </td> </tr> <tr> <td><strong>ignores_request.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-06098845100f93443eaa531928a39a803862d1031ccea9ecccc83b8658a58b52">+61/-51</a> </td> </tr> <tr> <td><strong>ignores_request_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-592f7e7bcfc9e8bde581d845d4ae40f18b2f5c70aeb9d9f9481c92439c3f0e74">+35/-46</a> </td> </tr> <tr> <td><strong>ldx_sync_service.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-96079acff1e919961c5c93b80089075c62ed6b1f044fcf18fa0021dcf86fd30b">+149/-119</a></td> </tr> <tr> <td><strong>ldx_sync_service_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-aca1dc6a8fa97db48aa613e9fe3d8e075ff47071ab18848a1369c1217bf8863e">+438/-208</a></td> </tr> <tr> <td><strong>login.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-21b93267e7967e84d95e104e3b17f130b4b47b4a37ac176c5bba7dd4c35cee31">+10/-6</a> </td> </tr> <tr> <td><strong>logout.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-22e316f4a260c54802f276ff85692d92b3c1aba01d3dfd7d73f313c567fb5aab">+5/-3</a> </td> </tr> <tr> <td><strong>logout_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-e3d549e46654c52dd2506b8941fc83546f129917fb37045d8e1bb4c8eb4d1c91">+12/-8</a> </td> </tr> <tr> <td><strong>ldx_sync_service_mock.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-3c7bf69a15757a5bbe63c8758c6596bee98f8b3d7d7b6a9664fc7502ee05f7ed">+6/-5</a> </td> </tr> <tr> <td><strong>navigate_to_range_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-1cde128b3e8be4bc13c1ae238266409330a5bcef310bee386343660b932056b8">+12/-12</a> </td> </tr> <tr> <td><strong>report_analytics.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-62743cd3ce4566b6111230201a62f4d1fea670f1fd60c593265bde16353d8585">+10/-6</a> </td> </tr> <tr> <td><strong>report_analytics_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-20363c3fc3625f9eba95434b9eac8946f2aad36f0ca47165d56a412a78da766a">+29/-29</a> </td> </tr> <tr> <td><strong>sast_enabled.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-66bf16df3a0885d711b00264fad42f006b0346950036f8b48dc7ae6478dc6df4">+1/-1</a> </td> </tr> <tr> <td><strong>toggle_tree_filter_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-b68b006463ac72f1f5bd3786814cdcd0b103cac0245c1f3fdc0efbd0266c6b63">+25/-24</a> </td> </tr> <tr> <td><strong>update_folder_config.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-a05ebb1468908293f4d3cfe250b1748079a0b150076d62ba0df69156131ea8c7">+28/-17</a> </td> </tr> <tr> <td><strong>update_folder_config_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-ded99b4b398d892e849ca2c76051626e1fec77a62c3b6d777e532cf09653f049">+37/-33</a> </td> </tr> <tr> <td><strong>workspace_folder_scan.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-6cb7a834c5afbe811a8145bd6d12892ca661ae68a983846d9f8077beabd6e757">+10/-6</a> </td> </tr> <tr> <td><strong>workspace_scan.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-7815afb61f4ee4d064ffc994582c7306f6ba37d1014c9db5d44ee109dbdc6682">+5/-3</a> </td> </tr> <tr> <td><strong>initializer.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-549679250b6998b23ae6754c4684adc9c107201a71db89c46e227fcc2b6c3a9d">+5/-3</a> </td> </tr> <tr> <td><strong>tree_builder.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-13a01423d69e8880eef4d1b357edd592e256151c20fe2e708922ec9f369d258e">+7/-3</a> </td> </tr> <tr> <td><strong>tree_html.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-47c0b3a66e860f79eb96752b6c2d226c640efecc95340807757164ca16cf1f85">+8/-7</a> </td> </tr> <tr> <td><strong>tree_html_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-a05e59c0bf8dd60c31ffcd4d99f9c41b4e14113da3327539b810a53f4f99c00d">+56/-56</a> </td> </tr> <tr> <td><strong>tree_node_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-914f0695e35f0166328ffb0e48acb6527945999894fce96f1292a00f29fabc64">+1/-1</a> </td> </tr> <tr> <td><strong>tree_scan_emitter.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-c86a1bb522364b4f14326b1a2915a724532c1d4f10d39ed3a51ca4a648715456">+13/-8</a> </td> </tr> <tr> <td><strong>tree_scan_emitter_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-406a88e6d83f47e407cb1bd5a26bd0967e5866aa11529d659a54afd480d356f0">+23/-19</a> </td> </tr> <tr> <td><strong>folder_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-bb03ee76aabde8be49355b245229584151a114e49ec791407738dcaeb631acaf">+138/-162</a></td> </tr> <tr> <td><strong>workspace_trust_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-ac8e52aa69f3b6fb4fd604078ddeef7df2cfe4814df32258a855a7e2254d9af1">+4/-2</a> </td> </tr> <tr> <td><strong>scan_state_aggregator_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-dacb10414b37097b40d2960a603ee1a3ec84ee95c6d096386bceb1c5aa893b42">+65/-51</a> </td> </tr> <tr> <td><strong>summary_html_external_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-f9eb5dd6ed9a5462d93db22db8c10746d506824a6f2927b6ef59869a6f53b592">+15/-7</a> </td> </tr> <tr> <td><strong>issues.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-4bdec45b5c8738e4bf742694b67c57c1102cfa09083bd638e325bfa650f8362a">+0/-3</a> </td> </tr> <tr> <td><strong>git_persistence_provider_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-d11404eaca9a26e07e5b47c9a72b80378bfadb2ba02238363b7a445faf6ad955">+80/-79</a> </td> </tr> <tr> <td><strong>base_scan.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-f37e6aa696f750af79d9ed24805074033bcea09bd38405ca384d14e4c63135f4">+43/-20</a> </td> </tr> <tr> <td><strong>base_scan_test.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-29ac0a06174ae18093e1504044ee8b0ef1574ab063ca1a5c9210e28cba07b6ea">+47/-39</a> </td> </tr> <tr> <td><strong>pre_scan_command.go</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-eb3aa1acbc37cb13f25f84053ef3e81f4f48f558536a7d5e99a3fe429e4878f8">+10/-4</a> </td> </tr> <tr> <td><strong>Additional files not shown</strong></td> <td><a href="https://github.com/snyk/snyk-ls/pull/1162/changes#diff-2f328e4cd8dbe3ad193e49d92bcf045f47a6b72b1e9487d366f6b8288589b4ca"></a></td> </tr> </table></details></td></tr></tr></tbody></table> </details> ___