Skip to content

Commit cadddf0

Browse files
committed
Remove Settings class, use VS Code config API directly
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
1 parent 01e8ef8 commit cadddf0

16 files changed

Lines changed: 249 additions & 586 deletions

eslint.config.mjs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ export default defineConfig(
1818
rules: {
1919
"@typescript-eslint/explicit-function-return-type": "error",
2020
"@typescript-eslint/no-empty-object-type": "off",
21+
// VS Code's .get<T>(key, default) needs explicit type params to
22+
// widen literal defaults (e.g. true -> boolean), otherwise
23+
// no-unnecessary-condition fires on the result.
24+
"@typescript-eslint/no-unnecessary-type-arguments": "off",
2125
"@typescript-eslint/no-floating-promises": [
2226
"error",
2327
{

src/extension.ts

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,7 @@ import { ShowHelpFeature } from "./features/ShowHelp";
2727
import { LanguageClientConsumer } from "./languageClientConsumer";
2828
import { Logger } from "./logging";
2929
import { SessionManager } from "./session";
30-
import { getSettings } from "./settings";
31-
import { PowerShellLanguageId, sleep } from "./utils";
30+
import { sleep } from "./utils";
3231
// The 1DS telemetry key, which is just shared among all Microsoft extensions
3332
// (and isn't sensitive).
3433
const TELEMETRY_KEY =
@@ -56,13 +55,8 @@ export async function activate(
5655

5756
telemetryReporter = new TelemetryReporter(TELEMETRY_KEY);
5857

59-
const settings = getSettings();
60-
logger.writeDebug(
61-
`Loaded settings:\n${JSON.stringify(settings, undefined, 2)}`,
62-
);
63-
6458
languageConfigurationDisposable = vscode.languages.setLanguageConfiguration(
65-
PowerShellLanguageId,
59+
"powershell",
6660
{
6761
// TODO: Remove the useless escapes
6862
wordPattern:
@@ -148,7 +142,6 @@ export async function activate(
148142

149143
sessionManager = new SessionManager(
150144
context,
151-
settings,
152145
logger,
153146
documentSelector,
154147
packageInfo.name,
@@ -204,7 +197,10 @@ export async function activate(
204197

205198
sessionManager.setLanguageClientConsumers(languageClientConsumers);
206199

207-
if (settings.startAutomatically) {
200+
const startAutomatically = vscode.workspace
201+
.getConfiguration("powershell")
202+
.get<boolean>("startAutomatically", true);
203+
if (startAutomatically) {
208204
await sessionManager.start();
209205
}
210206

src/features/Console.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import {
1010
} from "../controls/checkboxQuickPick";
1111
import { LanguageClientConsumer } from "../languageClientConsumer";
1212
import type { ILogger } from "../logging";
13-
import { getSettings } from "../settings";
1413

1514
export const EvaluateRequestType = new RequestType<
1615
IEvaluateRequestArguments,
@@ -215,9 +214,11 @@ export class ConsoleFeature extends LanguageClientConsumer {
215214
// We need to honor the focusConsoleOnExecute setting here too. However, the boolean that `show`
216215
// takes is called `preserveFocus` which when `true` the terminal will not take focus.
217216
// This is the inverse of focusConsoleOnExecute so we have to inverse the boolean.
217+
const focusConsoleOnExecute = vscode.workspace
218+
.getConfiguration("powershell.integratedConsole")
219+
.get<boolean>("focusConsoleOnExecute", true);
218220
vscode.window.activeTerminal.show(
219-
!getSettings().integratedConsole
220-
.focusConsoleOnExecute,
221+
!focusConsoleOnExecute,
221222
);
222223
await vscode.commands.executeCommand(
223224
"workbench.action.terminal.scrollToBottom",

src/features/DebugSession.ts

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ import type { ILogger } from "../logging";
3636
import { OperatingSystem, getPlatformDetails } from "../platform";
3737
import { PowerShellProcess } from "../process";
3838
import { SessionManager, type IEditorServicesSessionDetails } from "../session";
39-
import { getSettings } from "../settings";
4039
import { checkIfFileExists } from "../utils";
4140

4241
export const StartDebuggerNotificationType = new NotificationType<void>(
@@ -358,10 +357,12 @@ export class DebugSessionFeature
358357
// Prevent the Debug Console from opening
359358
config.internalConsoleOptions = "neverOpen";
360359

361-
const settings = getSettings();
362-
config.createTemporaryIntegratedConsole ??=
363-
settings.debugging.createTemporaryIntegratedConsole;
364-
config.executeMode ??= settings.debugging.executeMode;
360+
config.createTemporaryIntegratedConsole ??= workspace
361+
.getConfiguration("powershell.debugging")
362+
.get<boolean>("createTemporaryIntegratedConsole");
363+
config.executeMode ??= workspace
364+
.getConfiguration("powershell.debugging")
365+
.get("executeMode", "DotSource");
365366
if (config.request === "attach") {
366367
resolvedConfig = await this.resolveAttachDebugConfiguration(config);
367368
} else if (config.request === "launch") {
@@ -499,12 +500,10 @@ export class DebugSessionFeature
499500
private async createTemporaryIntegratedConsole(
500501
session: DebugSession,
501502
): Promise<IEditorServicesSessionDetails | undefined> {
502-
const settings = getSettings();
503503
const previousActiveTerminal = window.activeTerminal;
504504

505505
this.tempDebugProcess =
506506
await this.sessionManager.createDebugSessionProcess(
507-
settings,
508507
session.configuration.sessionName,
509508
);
510509
// TODO: Maybe set a timeout on the cancellation token?
@@ -665,11 +664,9 @@ export class DebugSessionFeature
665664

666665
/** Fetches all available vscode launch configurations. This is abstracted out for easier testing. */
667666
private getLaunchConfigurations(): DebugConfiguration[] {
668-
return (
669-
workspace
670-
.getConfiguration("launch")
671-
.get<DebugConfiguration[]>("configurations") ?? []
672-
);
667+
return workspace
668+
.getConfiguration("launch")
669+
.get<DebugConfiguration[]>("configurations", []);
673670
}
674671

675672
private async resolveAttachDebugConfiguration(
@@ -823,12 +820,10 @@ class PowerShellDebugAdapterTrackerFactory
823820
* user re-enables, then logging resumes.
824821
*/
825822
get log(): LogOutputChannel | undefined {
826-
if (
827-
workspace
828-
.getConfiguration("powershell.developer")
829-
.get<boolean>("traceDap") &&
830-
this._log === undefined
831-
) {
823+
const traceDap = workspace
824+
.getConfiguration("powershell.developer")
825+
.get<boolean>("traceDap");
826+
if (traceDap && this._log === undefined) {
832827
this._log = window.createOutputChannel(
833828
`${this.adapterName}: Trace DAP`,
834829
{ log: true },

src/features/ExtensionCommands.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
import { LanguageClient } from "vscode-languageclient/node";
1414
import { LanguageClientConsumer } from "../languageClientConsumer";
1515
import type { ILogger } from "../logging";
16-
import { getSettings, validateCwdSetting } from "../settings";
16+
import { validateCwdSetting } from "../settings";
1717
import { DebugConfig, DebugConfigurations } from "./DebugSession";
1818

1919
export interface IExtensionCommand {
@@ -311,9 +311,10 @@ export class ExtensionCommandsFeature extends LanguageClientConsumer {
311311
languageClient.onNotification(ClearTerminalNotificationType, () => {
312312
// We check to see if they have TrueClear on. If not, no-op because the
313313
// overriden Clear-Host already calls [System.Console]::Clear()
314-
if (
315-
getSettings().integratedConsole.forceClearScrollbackBuffer
316-
) {
314+
const forceClearScrollbackBuffer = vscode.workspace
315+
.getConfiguration("powershell.integratedConsole")
316+
.get<boolean>("forceClearScrollbackBuffer");
317+
if (forceClearScrollbackBuffer) {
317318
void vscode.commands.executeCommand(
318319
"workbench.action.terminal.clear",
319320
);

src/features/GetCommands.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import * as vscode from "vscode";
55
import { RequestType0 } from "vscode-languageclient";
66
import { LanguageClient } from "vscode-languageclient/node";
77
import { LanguageClientConsumer } from "../languageClientConsumer";
8-
import { getSettings } from "../settings";
98

109
interface ICommand {
1110
name: string;
@@ -79,7 +78,9 @@ export class GetCommandsFeature extends LanguageClientConsumer {
7978
private async CommandExplorerRefresh(): Promise<void> {
8079
const client = await LanguageClientConsumer.getLanguageClient();
8180
const result = await client.sendRequest(GetCommandRequestType);
82-
const exclusions = getSettings().sideBar.CommandExplorerExcludeFilter;
81+
const exclusions = vscode.workspace
82+
.getConfiguration("powershell.sideBar")
83+
.get<string[]>("CommandExplorerExcludeFilter", []);
8384
const excludeFilter = exclusions.map((filter: string) =>
8485
filter.toLowerCase(),
8586
);

src/features/HelpCompletion.ts

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@ import {
1414
import { RequestType } from "vscode-languageclient";
1515
import { LanguageClient } from "vscode-languageclient/node";
1616
import { LanguageClientConsumer } from "../languageClientConsumer";
17-
import { CommentType, getSettings, Settings } from "../settings";
17+
18+
enum CommentType {
19+
Disabled = "Disabled",
20+
BlockComment = "BlockComment",
21+
LineComment = "LineComment",
22+
}
1823

1924
interface ICommentHelpRequestArguments {}
2025

@@ -37,13 +42,14 @@ enum SearchState {
3742
export class HelpCompletionFeature extends LanguageClientConsumer {
3843
private helpCompletionProvider: HelpCompletionProvider | undefined;
3944
private disposable: Disposable | undefined;
40-
private settings: Settings;
4145

4246
constructor() {
4347
super();
44-
this.settings = getSettings();
4548

46-
if (this.settings.helpCompletion !== CommentType.Disabled) {
49+
const helpCompletion = workspace
50+
.getConfiguration("powershell")
51+
.get<CommentType>("helpCompletion", CommentType.BlockComment);
52+
if (helpCompletion !== CommentType.Disabled) {
4753
this.helpCompletionProvider = new HelpCompletionProvider();
4854
this.disposable = workspace.onDidChangeTextDocument(async (e) => {
4955
await this.onEvent(e);
@@ -144,12 +150,10 @@ class HelpCompletionProvider extends LanguageClientConsumer {
144150
private triggerFinderHelpComment: TriggerFinder;
145151
private lastChangeRange: Range | undefined;
146152
private lastDocument: TextDocument | undefined;
147-
private settings: Settings;
148153

149154
constructor() {
150155
super();
151156
this.triggerFinderHelpComment = new TriggerFinder("##");
152-
this.settings = getSettings();
153157
}
154158

155159
public get triggerFound(): boolean {
@@ -187,11 +191,13 @@ class HelpCompletionProvider extends LanguageClientConsumer {
187191
const doc = this.lastDocument;
188192

189193
const client = await LanguageClientConsumer.getLanguageClient();
194+
const helpCompletion = workspace
195+
.getConfiguration("powershell")
196+
.get<CommentType>("helpCompletion", CommentType.BlockComment);
190197
const result = await client.sendRequest(CommentHelpRequestType, {
191198
documentUri: doc.uri.toString(),
192199
triggerPosition: triggerStartPos,
193-
blockComment:
194-
this.settings.helpCompletion === CommentType.BlockComment,
200+
blockComment: helpCompletion === CommentType.BlockComment,
195201
});
196202

197203
if (result.content.length === 0) {

src/features/PesterTests.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import * as path from "path";
55
import type { ILogger } from "../logging";
66
import { SessionManager } from "../session";
7-
import { getChosenWorkspace, getSettings } from "../settings";
7+
import { getChosenWorkspace } from "../settings";
88
import vscode = require("vscode");
99
import utils = require("../utils");
1010

@@ -115,7 +115,11 @@ export class PesterTestsFeature implements vscode.Disposable {
115115
lineNum?: number,
116116
outputPath?: string,
117117
): vscode.DebugConfiguration {
118-
const settings = getSettings();
118+
const debuggingConfig = vscode.workspace.getConfiguration(
119+
"powershell.debugging",
120+
);
121+
const pesterConfig =
122+
vscode.workspace.getConfiguration("powershell.pester");
119123
const launchConfig = {
120124
request: "launch",
121125
type: "PowerShell",
@@ -127,8 +131,9 @@ export class PesterTestsFeature implements vscode.Disposable {
127131
],
128132
internalConsoleOptions: "neverOpen",
129133
noDebug: launchType === LaunchType.Run,
130-
createTemporaryIntegratedConsole:
131-
settings.debugging.createTemporaryIntegratedConsole,
134+
createTemporaryIntegratedConsole: debuggingConfig.get<boolean>(
135+
"createTemporaryIntegratedConsole",
136+
),
132137
};
133138

134139
if (lineNum) {
@@ -142,19 +147,23 @@ export class PesterTestsFeature implements vscode.Disposable {
142147
launchConfig.args.push("-All");
143148
}
144149

145-
if (!settings.pester.useLegacyCodeLens) {
150+
const useLegacyCodeLens = pesterConfig.get<boolean>(
151+
"useLegacyCodeLens",
152+
true,
153+
);
154+
if (!useLegacyCodeLens) {
146155
launchConfig.args.push("-MinimumVersion5");
147156
}
148157

149158
if (launchType === LaunchType.Debug) {
150159
launchConfig.args.push(
151160
"-Output",
152-
`'${settings.pester.debugOutputVerbosity}'`,
161+
`'${pesterConfig.get("debugOutputVerbosity", "Diagnostic")}'`,
153162
);
154163
} else {
155164
launchConfig.args.push(
156165
"-Output",
157-
`'${settings.pester.outputVerbosity}'`,
166+
`'${pesterConfig.get("outputVerbosity", "FromPreference")}'`,
158167
);
159168
}
160169

src/features/UpdatePowerShell.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import vscode = require("vscode");
66

77
import type { ILogger } from "../logging";
88
import type { IPowerShellVersionDetails } from "../session";
9-
import { changeSetting, Settings } from "../settings";
9+
import { changeSetting } from "../settings";
1010

1111
interface IUpdateMessageItem extends vscode.MessageItem {
1212
id: number;
@@ -39,7 +39,6 @@ export class UpdatePowerShell {
3939
private localVersion: SemVer;
4040

4141
constructor(
42-
private sessionSettings: Settings,
4342
private logger: ILogger,
4443
versionDetails: IPowerShellVersionDetails,
4544
) {
@@ -52,7 +51,10 @@ export class UpdatePowerShell {
5251

5352
private shouldCheckForUpdate(): boolean {
5453
// Respect user setting.
55-
if (!this.sessionSettings.promptToUpdatePowerShell) {
54+
const promptToUpdatePowerShell = vscode.workspace
55+
.getConfiguration("powershell")
56+
.get<boolean>("promptToUpdatePowerShell", true);
57+
if (!promptToUpdatePowerShell) {
5658
this.logger.writeDebug(
5759
"Setting 'promptToUpdatePowerShell' was false.",
5860
);

src/platform.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,7 @@ import * as process from "process";
77
import untildify from "untildify";
88
import { integer } from "vscode-languageserver-protocol";
99
import type { ILogger } from "./logging";
10-
import {
11-
changeSetting,
12-
getSettings,
13-
type PowerShellAdditionalExePathSettings,
14-
} from "./settings";
10+
import { changeSetting } from "./settings";
1511
import * as utils from "./utils";
1612
import vscode = require("vscode");
1713

@@ -93,7 +89,7 @@ export class PowerShellExeFinder {
9389
// The platform details descriptor for the platform we're on
9490
private platformDetails: IPlatformDetails,
9591
// Additional configured PowerShells
96-
private additionalPowerShellExes: PowerShellAdditionalExePathSettings,
92+
private additionalPowerShellExes: Record<string, string>,
9793
private logger?: ILogger,
9894
) {}
9995

@@ -169,7 +165,10 @@ export class PowerShellExeFinder {
169165
const message = `Additional PowerShell '${additionalPwsh.displayName}' not found at '${additionalPwsh.exePath}'!`;
170166
this.logger?.writeWarning(message);
171167

172-
if (!getSettings().suppressAdditionalExeNotFoundWarning) {
168+
const suppressAdditionalExeNotFoundWarning = vscode.workspace
169+
.getConfiguration("powershell")
170+
.get<boolean>("suppressAdditionalExeNotFoundWarning");
171+
if (!suppressAdditionalExeNotFoundWarning) {
173172
const selection = await vscode.window.showWarningMessage(
174173
message,
175174
"Don't Show Again",

0 commit comments

Comments
 (0)