Remove Settings class, use VS Code config API directly#5464
Remove Settings class, use VS Code config API directly#5464andyleejordan wants to merge 1 commit intomainfrom
Conversation
Replace the cached Settings class hierarchy with direct `vscode.workspace.getConfiguration()` calls throughout the codebase. This eliminates race conditions from stale cached values and removes the burden of keeping the class in sync with package.json. - Remove Settings, DebuggingSettings, DeveloperSettings, etc. classes - Remove getSettings(), getSetting(), getEffectiveConfigurationTarget(), onSettingChange(), and onPowerShellSettingChange() helpers - Remove PowerShellLanguageId constant (inline "powershell" literal) - Remove unused enums: StartLocation, ExecuteMode, CodeFormattingPreset, PipelineIndentationStyle - Move CommentType enum to HelpCompletion.ts (its only consumer) - Replace restartOnCriticalConfigChange() stale-vs-fresh comparisons with affectsConfiguration() calls - Replace powerShellDefaultVersion mutation with dedicated powerShellVersionOverride field - Audit and fix all setting defaults to match package.json - Disable no-unnecessary-type-arguments ESLint rule (conflicts with no-unnecessary-condition when using VS Code .get<T>(key, default) API) - Update tests
|
This used the new Planning Agent, with the following plan (and maybe an hour or two of review and follow-up fixes and refactors) with Claude Opus 4.6: Plan: Remove Settings class, use VS Code APIs directlyTL;DRRemove the Key Design Decisions
PhasesPhase 1: Add thin config helpers to settings.tsAdd a helper function (e.g., Keep the existing Files: Phase 2: Migrate session.ts
Files: Phase 3: Migrate process.ts
Files: Phase 4: Migrate feature files (parallelizable)Each feature file can be migrated independently:
Files: All feature files listed above Phase 5: Remove Settings class from settings.ts
Files: Relevant Files
Verification
Scope
Design Decisions (confirmed)
|
There was a problem hiding this comment.
Pull request overview
This PR removes the cached Settings class hierarchy and migrates the extension to read/update configuration via vscode.workspace.getConfiguration() directly, aiming to avoid stale cached values and simplify keeping settings in sync with package.json.
Changes:
- Replaced
Settingsobject usage across runtime/features with direct VS Code configuration reads/updates. - Updated session restart detection to rely on
ConfigurationChangeEvent.affectsConfiguration()instead of stale-vs-fresh comparisons. - Updated E2E/unit tests and adjusted ESLint configuration to accommodate the new
.get<T>(key, default)usage pattern.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| test/features/UpdatePowerShell.test.ts | Updates tests to toggle VS Code config instead of mutating a Settings instance. |
| test/core/settings.test.ts | Removes Settings/helper-based assertions; validates config updates via vscode.workspace.getConfiguration(). |
| src/utils.ts | Removes PowerShellLanguageId constant (call sites now inline "powershell"). |
| src/settings.ts | Removes the Settings model + helpers; keeps changeSetting, getChosenWorkspace, and validateCwdSetting using VS Code config API. |
| src/session.ts | Removes stored Settings dependency; reads config on demand; refactors restart logic and PowerShell version selection. |
| src/process.ts | Removes Settings injection; reads integrated console + developer settings directly from configuration. |
| src/platform.ts | Uses config API directly for suppression setting; simplifies additional-exe-paths type. |
| src/features/UpdatePowerShell.ts | Reads promptToUpdatePowerShell directly from configuration. |
| src/features/PesterTests.ts | Reads debugging/pester settings via configuration objects. |
| src/features/HelpCompletion.ts | Moves CommentType locally and reads helpCompletion from configuration instead of cached settings. |
| src/features/GetCommands.ts | Reads sidebar exclusion filter directly from configuration. |
| src/features/ExtensionCommands.ts | Reads console “force clear scrollback” directly from configuration. |
| src/features/DebugSession.ts | Resolves debug defaults directly from configuration. |
| src/features/Console.ts | Reads focusConsoleOnExecute directly from configuration. |
| src/extension.ts | Removes initial settings load/log; uses config directly for language id and auto-start. |
| eslint.config.mjs | Disables @typescript-eslint/no-unnecessary-type-arguments to avoid conflicts with VS Code config .get<T>(..., default) patterns. |
Comments suppressed due to low confidence (2)
src/session.ts:363
powerShellVersionOverrideis set whenrestartSession()is called withexeNameOverride, but it is never cleared whenrestartSession()is called without an override. After a single overridden restart (e.g. from the session menu), subsequent plain restarts will continue to prefer the old override over the configuredpowershell.powerShellDefaultVersion, which differs from the prior behavior when settings were reloaded each restart. Consider clearingpowerShellVersionOverridewhen no override is requested (or explicitly making/communicating the override as sticky by design).
private async restartSession(exeNameOverride?: string): Promise<void> {
this.logger.write("Restarting session...");
await this.stop();
if (exeNameOverride) {
// Reset the version and PowerShell details since we're launching a
// new executable.
this.logger.writeDebug(
`Starting with executable overriden to: ${exeNameOverride}`,
);
this.powerShellVersionOverride = exeNameOverride;
this.versionDetails = undefined;
this.PowerShellExeDetails = undefined;
}
await this.start();
}
src/session.ts:719
- In the warning when the requested PowerShell display name isn't found, the message hard-codes "The 'powerShellDefaultVersion' setting was ...". After introducing
powerShellVersionOverride,wantedNamemay come from the override rather than the setting, so this message can be misleading. Consider rewording to refer to the requested/selected PowerShell name (and optionally mention whether it came from the override vs configuration).
wantedName ??=
this.powerShellVersionOverride ??
vscode.workspace
.getConfiguration("powershell")
.get("powerShellDefaultVersion", "");
if (wantedName !== "") {
for await (const details of powershellExeFinder.enumeratePowerShellInstallations()) {
// Need to compare names case-insensitively, from https://stackoverflow.com/a/2140723
if (
wantedName.localeCompare(
details.displayName,
undefined,
{ sensitivity: "accent" },
) === 0
) {
defaultPowerShell = details;
break;
}
}
}
foundPowerShell =
defaultPowerShell ??
(await powershellExeFinder.getFirstAvailablePowerShellInstallation());
if (
wantedName !== "" &&
defaultPowerShell === undefined &&
foundPowerShell !== undefined
) {
void this.logger.writeAndShowWarning(
`The 'powerShellDefaultVersion' setting was '${wantedName}' but this was not found!` +
` Instead using first available installation '${foundPowerShell.displayName}' at '${foundPowerShell.exePath}'!`,
);
| // Create a folder for the session files. | ||
| await vscode.workspace.fs.createDirectory(this.sessionsFolder); | ||
|
|
||
| // Migrate things. | ||
| await this.migrateWhitespaceAroundPipeSetting(); | ||
|
|
||
| // Update non-PowerShell settings. | ||
| this.shellIntegrationEnabled = | ||
| vscode.workspace | ||
| .getConfiguration("terminal.integrated.shellIntegration") | ||
| .get<boolean>("enabled") ?? false; | ||
| this.shellIntegrationEnabled = vscode.workspace | ||
| .getConfiguration("terminal.integrated.shellIntegration") | ||
| .get<boolean>("enabled", false); |
There was a problem hiding this comment.
package.json still marks powershell.codeFormatting.whitespaceAroundPipe as deprecated and says the extension will automatically migrate it to codeFormatting.addWhitespaceAroundPipe, but the migration logic (migrateWhitespaceAroundPipeSetting) and its invocation were removed. This means existing users with the deprecated setting set will no longer be migrated as promised. Consider reinstating the migration (or updating the package.json deprecation text if migration is intentionally removed).
| // Reset the version and PowerShell details since we're launching a | ||
| // new executable. | ||
| this.logger.writeDebug( | ||
| `Starting with executable overriden to: ${exeNameOverride}`, |
There was a problem hiding this comment.
Spelling in the debug log message: "overriden" should be "overridden".
| `Starting with executable overriden to: ${exeNameOverride}`, | |
| `Starting with executable overridden to: ${exeNameOverride}`, |
Summary
Replace the cached
Settingsclass hierarchy with directvscode.workspace.getConfiguration()calls throughout the codebase. This eliminates race conditions from stale cached values and removes the burden of keeping the class in sync withpackage.json.Changes
Settings,DebuggingSettings,DeveloperSettings, etc. classes and all nested settings typesgetSettings(),getSetting(),getEffectiveConfigurationTarget(),onSettingChange(), andonPowerShellSettingChange()helpersPowerShellLanguageIdconstant (inline"powershell"literal)StartLocation,ExecuteMode,CodeFormattingPreset,PipelineIndentationStyleCommentTypeenum toHelpCompletion.ts(its only consumer)restartOnCriticalConfigChange()stale-vs-fresh setting comparisons withaffectsConfiguration()calls, fixing race conditionspowerShellDefaultVersionmutation with a dedicatedpowerShellVersionOverridefieldpackage.json(found mismatches ineditorServicesLogLevelandexecuteMode)no-unnecessary-type-argumentsESLint rule (conflicts withno-unnecessary-conditionwhen using VS Code's.get<T>(key, default)API)Motivation
The
Settingsclass cached configuration values at startup and on change events, but:restartOnCriticalConfigChange()compared stale cached values against fresh reads, which could miss changespackage.jsonrequired a corresponding field in the classsessionSettings.foocould get outdated values if the config changed between readsThe VS Code API
vscode.workspace.getConfiguration()always returns current values andConfigurationChangeEvent.affectsConfiguration()reliably detects changes.