Skip to content

Commit 2ac7434

Browse files
committed
Log when settings are changed by extension
1 parent db19101 commit 2ac7434

File tree

5 files changed

+51
-33
lines changed

5 files changed

+51
-33
lines changed

src/features/UpdatePowerShell.ts

+16-7
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import * as util from "util";
1212
import { MessageItem, ProgressLocation, window } from "vscode";
1313

1414
import { LanguageClient } from "vscode-languageclient/node";
15+
import { Logger } from "../logging";
1516
import { SessionManager } from "../session";
1617
import * as Settings from "../settings";
1718
import { isMacOS, isWindows } from "../utils";
@@ -21,7 +22,7 @@ const streamPipeline = util.promisify(stream.pipeline);
2122

2223
const PowerShellGitHubReleasesUrl =
2324
"https://api.github.com/repos/PowerShell/PowerShell/releases/latest";
24-
const PowerShellGitHubPrereleasesUrl =
25+
const PowerShellGitHubPreReleasesUrl =
2526
"https://api.github.com/repos/PowerShell/PowerShell/releases";
2627

2728
export class GitHubReleaseInformation {
@@ -40,7 +41,7 @@ export class GitHubReleaseInformation {
4041

4142
// Fetch the latest PowerShell releases from GitHub.
4243
const response = await fetch(
43-
preview ? PowerShellGitHubPrereleasesUrl : PowerShellGitHubReleasesUrl,
44+
preview ? PowerShellGitHubPreReleasesUrl : PowerShellGitHubReleasesUrl,
4445
requestConfig);
4546

4647
if (!response.ok) {
@@ -85,7 +86,8 @@ export async function InvokePowerShellUpdateCheck(
8586
languageServerClient: LanguageClient,
8687
localVersion: semver.SemVer,
8788
arch: string,
88-
release: GitHubReleaseInformation) {
89+
release: GitHubReleaseInformation,
90+
logger: Logger) {
8991
const options: IUpdateMessageItem[] = [
9092
{
9193
id: 0,
@@ -103,6 +105,7 @@ export async function InvokePowerShellUpdateCheck(
103105

104106
// If our local version is up-to-date, we can return early.
105107
if (semver.compare(localVersion, release.version) >= 0) {
108+
logger.writeDiagnostic("PowerShell is up-to-date!");
106109
return;
107110
}
108111

@@ -111,8 +114,7 @@ export async function InvokePowerShellUpdateCheck(
111114
}.`;
112115

113116
if (process.platform === "linux") {
114-
await window.showInformationMessage(
115-
`${commonText} We recommend updating to the latest version.`);
117+
void logger.writeAndShowInformation(`${commonText} We recommend updating to the latest version.`);
116118
return;
117119
}
118120

@@ -122,7 +124,10 @@ export async function InvokePowerShellUpdateCheck(
122124
}`, ...options);
123125

124126
// If the user cancels the notification.
125-
if (!result) { return; }
127+
if (!result) {
128+
logger.writeDiagnostic("User canceled PowerShell update prompt.");
129+
return;
130+
}
126131

127132
// Yes choice.
128133
switch (result.id) {
@@ -152,6 +157,7 @@ export async function InvokePowerShellUpdateCheck(
152157
});
153158

154159
// Stop the session because Windows likes to hold on to files.
160+
logger.writeDiagnostic("MSI downloaded, stopping session and closing terminals!");
155161
await sessionManager.stop();
156162

157163
// Close all terminals with the name "pwsh" in the current VS Code session.
@@ -164,10 +170,12 @@ export async function InvokePowerShellUpdateCheck(
164170
}
165171

166172
// Invoke the MSI via cmd.
173+
logger.writeDiagnostic(`Running '${msiDownloadPath}' to update PowerShell...`);
167174
const msi = spawn("msiexec", ["/i", msiDownloadPath]);
168175

169176
msi.on("close", () => {
170177
// Now that the MSI is finished, restart the session.
178+
logger.writeDiagnostic("MSI installation finished, restarting session.");
171179
void sessionManager.start();
172180
fs.unlinkSync(msiDownloadPath);
173181
});
@@ -177,6 +185,7 @@ export async function InvokePowerShellUpdateCheck(
177185
? "brew upgrade --cask powershell-preview"
178186
: "brew upgrade --cask powershell";
179187

188+
logger.writeDiagnostic(`Running '${script}' to update PowerShell...`);
180189
await languageServerClient.sendRequest(EvaluateRequestType, {
181190
expression: script,
182191
});
@@ -186,7 +195,7 @@ export async function InvokePowerShellUpdateCheck(
186195

187196
// Never choice.
188197
case 2:
189-
await Settings.change("promptToUpdatePowerShell", false, true);
198+
await Settings.change("promptToUpdatePowerShell", false, true, logger);
190199
break;
191200
default:
192201
break;

src/main.ts

+12-7
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ const PackageJSON: any = require("../package.json");
3737
// the application insights key (also known as instrumentation key) used for telemetry.
3838
const AI_KEY = "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217";
3939

40+
let languageConfigurationDisposable: vscode.Disposable;
4041
let logger: Logger;
4142
let sessionManager: SessionManager;
4243
let languageClientConsumers: LanguageClientConsumer[] = [];
@@ -50,21 +51,27 @@ const documentSelector: DocumentSelector = [
5051

5152
// NOTE: Now that this is async, we can probably improve a lot!
5253
export async function activate(context: vscode.ExtensionContext): Promise<IPowerShellExtensionClient> {
54+
// Setup the logger. These settings cannot be passed to subsequent classes
55+
// as the `cwd` hasn't been validated!
56+
const earlySettings = Settings.load();
57+
logger = new Logger(context.globalStorageUri);
58+
logger.MinimumLogLevel = Logger.logLevelNameToValue(earlySettings.developer.editorServicesLogLevel);
59+
5360
telemetryReporter = new TelemetryReporter(PackageJSON.name, PackageJSON.version, AI_KEY);
5461

5562
// If both extensions are enabled, this will cause unexpected behavior since both register the same commands.
5663
// TODO: Merge extensions and use preview channel in marketplace instead.
5764
if (PackageJSON.name.toLowerCase() === "powershell-preview"
5865
&& vscode.extensions.getExtension("ms-vscode.powershell")) {
59-
void vscode.window.showErrorMessage(
66+
void logger.writeAndShowError(
6067
"'PowerShell' and 'PowerShell Preview' are both enabled. Please disable one for best performance.");
6168
}
6269

6370
// Load and validate settings (will prompt for 'cwd' if necessary).
64-
await Settings.validateCwdSetting();
71+
await Settings.validateCwdSetting(logger);
6572
const settings = Settings.load();
6673

67-
vscode.languages.setLanguageConfiguration(
74+
languageConfigurationDisposable = vscode.languages.setLanguageConfiguration(
6875
PowerShellLanguageId,
6976
{
7077
// TODO: Remove the useless escapes
@@ -125,10 +132,6 @@ export async function activate(context: vscode.ExtensionContext): Promise<IPower
125132
],
126133
});
127134

128-
// Setup the logger.
129-
logger = new Logger(context.globalStorageUri);
130-
logger.MinimumLogLevel = Logger.logLevelNameToValue(settings.developer.editorServicesLogLevel);
131-
132135
sessionManager = new SessionManager(
133136
context,
134137
settings,
@@ -202,4 +205,6 @@ export async function deactivate(): Promise<void> {
202205

203206
// Dispose of telemetry reporter
204207
await telemetryReporter.dispose();
208+
209+
languageConfigurationDisposable.dispose();
205210
}

src/session.ts

+7-6
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ export class SessionManager implements Middleware {
212212
await this.stop();
213213

214214
// Re-load and validate the settings.
215-
await Settings.validateCwdSetting();
215+
await Settings.validateCwdSetting(this.logger);
216216
this.sessionSettings = Settings.load();
217217

218218
await this.start(exeNameOverride);
@@ -348,8 +348,8 @@ export class SessionManager implements Middleware {
348348
const configurationTargetOfOldSetting = Settings.getEffectiveConfigurationTarget(deprecatedSetting);
349349
if (configurationTargetOfOldSetting !== undefined && configurationTargetOfNewSetting === undefined) {
350350
const value = configuration.get(deprecatedSetting, configurationTargetOfOldSetting);
351-
await Settings.change(newSetting, value, configurationTargetOfOldSetting);
352-
await Settings.change(deprecatedSetting, undefined, configurationTargetOfOldSetting);
351+
await Settings.change(newSetting, value, configurationTargetOfOldSetting, this.logger);
352+
await Settings.change(deprecatedSetting, undefined, configurationTargetOfOldSetting, this.logger);
353353
}
354354
}
355355

@@ -373,7 +373,7 @@ export class SessionManager implements Middleware {
373373

374374
this.suppressRestartPrompt = true;
375375
try {
376-
await Settings.change("powerShellExePath", undefined, true);
376+
await Settings.change("powerShellExePath", undefined, true, this.logger);
377377
} finally {
378378
this.suppressRestartPrompt = false;
379379
}
@@ -731,7 +731,8 @@ Type 'help' to get help.
731731
this.languageClient!,
732732
localVersion!,
733733
this.versionDetails!.architecture,
734-
release);
734+
release,
735+
this.logger);
735736
} catch (err) {
736737
// Best effort. This probably failed to fetch the data from GitHub.
737738
this.logger.writeWarning(err instanceof Error ? err.message : "unknown");
@@ -804,7 +805,7 @@ Type 'help' to get help.
804805
private async changePowerShellDefaultVersion(exePath: IPowerShellExeDetails) {
805806
this.suppressRestartPrompt = true;
806807
try {
807-
await Settings.change("powerShellDefaultVersion", exePath.displayName, true);
808+
await Settings.change("powerShellDefaultVersion", exePath.displayName, true, this.logger);
808809
} finally {
809810
this.suppressRestartPrompt = false;
810811
}

src/settings.ts

+13-10
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import vscode = require("vscode");
55
import utils = require("./utils");
66
import os = require("os");
7+
import { Logger } from "./logging";
78

89
enum CodeFormattingPreset {
910
Custom,
@@ -288,11 +289,17 @@ export async function change(
288289
settingName: string,
289290
// eslint-disable-next-line @typescript-eslint/no-explicit-any
290291
newValue: any,
291-
configurationTarget?: vscode.ConfigurationTarget | boolean): Promise<void> {
292+
configurationTarget: vscode.ConfigurationTarget | boolean | undefined,
293+
logger: Logger | undefined): Promise<void> {
292294

293-
const configuration = vscode.workspace.getConfiguration(utils.PowerShellLanguageId);
294-
// TODO: Consider wrapping with try/catch, but we can't log the error.
295-
await configuration.update(settingName, newValue, configurationTarget);
295+
logger?.writeDiagnostic(`Changing '${settingName}' at scope '${configurationTarget} to '${newValue}'`);
296+
297+
try {
298+
const configuration = vscode.workspace.getConfiguration(utils.PowerShellLanguageId);
299+
await configuration.update(settingName, newValue, configurationTarget);
300+
} catch (err) {
301+
logger?.writeError(`Failed to change setting: ${err}`);
302+
}
296303
}
297304

298305
function getWorkspaceSettingsWithDefaults<TSettings>(
@@ -311,7 +318,7 @@ function getWorkspaceSettingsWithDefaults<TSettings>(
311318
// We don't want to query the user more than once, so this is idempotent.
312319
let hasPrompted = false;
313320

314-
export async function validateCwdSetting(): Promise<string> {
321+
export async function validateCwdSetting(logger: Logger): Promise<string> {
315322
let cwd = vscode.workspace.getConfiguration(utils.PowerShellLanguageId).get<string | undefined>("cwd");
316323

317324
// Only use the cwd setting if it exists.
@@ -336,11 +343,7 @@ export async function validateCwdSetting(): Promise<string> {
336343
// Save the picked 'cwd' to the workspace settings.
337344
// We have to check again because the user may not have picked.
338345
if (cwd !== undefined && await utils.checkIfDirectoryExists(cwd)) {
339-
try {
340-
await change("cwd", cwd);
341-
} catch {
342-
// Could fail if workspace file is invalid.
343-
}
346+
await change("cwd", cwd, undefined, logger);
344347
}
345348
}
346349

test/core/settings.test.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,16 @@ describe("Settings module", function () {
1111
});
1212

1313
it("Updates correctly", async function () {
14-
await Settings.change("helpCompletion", "LineComment", false);
14+
await Settings.change("helpCompletion", "LineComment", false, undefined);
1515
assert.strictEqual(Settings.load().helpCompletion, "LineComment");
1616
});
1717

1818
it("Gets the effective configuration target", async function () {
19-
await Settings.change("helpCompletion", "LineComment", false);
19+
await Settings.change("helpCompletion", "LineComment", false, undefined);
2020
let target = Settings.getEffectiveConfigurationTarget("helpCompletion");
2121
assert.strictEqual(target, vscode.ConfigurationTarget.Workspace);
2222

23-
await Settings.change("helpCompletion", undefined, false);
23+
await Settings.change("helpCompletion", undefined, false, undefined);
2424
target = Settings.getEffectiveConfigurationTarget("helpCompletion");
2525
assert.strictEqual(target, undefined);
2626
});

0 commit comments

Comments
 (0)