Guidelines for using vscode.window.show*Message methods. Use when working with showInformationMessage, showWarningMessage, showErrorMessage.
| Category | DO | DON'T |
|---|---|---|
| API | Direct vscode.window.show*Message | Legacy NotificationService |
| Messages | nls.localize('key', ...args) | String literals or template literals without nls |
| Return Values | Handle Thenable<string | undefined> or Thenable<MessageItem | undefined> | Ignore return values |
| Button Actions | Check return value for button clicks | Assume user always clicks |
| Button Actions | nls.localize | String literals or template literals without nls |
| Modal Options | { modal: true, detail: ... } for blocking dialogs |
detail without modal: true (detail modal-only); explicit 'Cancel' buttons (VS Code adds one automatically) |
| Effect (wait) | Effect.promise() when response needed | Effect.promise() for fire-and-forget |
| Effect (no wait) | Effect.sync() for fire-and-forget | Effect.promise() when not waiting |
Use vscode.window.show*Message directly. Don't use legacy NotificationService in new code.
import * as vscode from 'vscode';
import { nls } from '../messages/messages';
// CORRECT
await vscode.window.showInformationMessage(nls.localize('retrieve_canceled'));
await vscode.window.showErrorMessage(nls.localize('retrieve_failed', String(error)));
// WRONG
await notificationService.showInformationMessage(nls.localize('retrieve_canceled'));
All message strings and button labels must use nls.localize(). Enforced by no-vscode-message-literals ESLint rule.
// CORRECT
await vscode.window.showInformationMessage(nls.localize('retrieve_canceled'));
await vscode.window.showErrorMessage(nls.localize('retrieve_failed', String(error)));
await vscode.window.showInformationMessage(`${nls.localize('prefix')} ${nls.localize('suffix')}`);
const answer = await vscode.window.showWarningMessage(
nls.localize('confirm_delete'),
nls.localize('yes_button'),
nls.localize('no_button')
);
// WRONG
await vscode.window.showInformationMessage('Operation successful');
await vscode.window.showInformationMessage(`Operation ${status} successful`);
await vscode.window.showWarningMessage(nls.localize('confirm_delete'), 'Yes', 'No');
Adding new messages:
i18n.ts in packagenls.localize('your_message_key', ...args)Returns clicked button or undefined if dismissed.
Return types:
Thenable<string | undefined>Thenable<MessageItem | undefined>// CORRECT - String buttons
const selection = await vscode.window.showWarningMessage(
nls.localize('unsaved_changes'),
nls.localize('save_button'),
nls.localize('discard_button')
);
if (selection === nls.localize('save_button')) {
await saveFile();
}
// CORRECT - MessageItem buttons
const item = await vscode.window.showWarningMessage(
nls.localize('unsaved_changes'),
{ modal: true },
{ title: nls.localize('save_button') },
{ title: nls.localize('discard_button') }
);
if (item?.title === nls.localize('save_button')) {
await saveFile();
}
// CORRECT - Fire and forget
void vscode.window.showInformationMessage(nls.localize('operation_completed'));
// WRONG
vscode.window.showInformationMessage(nls.localize('operation_completed')); // Missing void
Use Effect.promise() to wait for user response. Blocks execution until user responds.
import { Effect } from 'effect';
// CORRECT - Wait for response
const selection =
yield *
Effect.promise(() =>
vscode.window.showWarningMessage(nls.localize('confirm_action'), nls.localize('yes'), nls.localize('no'))
);
if (selection === nls.localize('yes')) {
yield * performAction();
}
// CORRECT - Wait for error acknowledgment
yield * Effect.promise(() => vscode.window.showErrorMessage(nls.localize('critical_error')));
Use Effect.sync() for non-blocking messages. Execution continues immediately.
import { Effect } from 'effect';
// CORRECT - Fire and forget
yield *
Effect.sync(() => {
void vscode.window.showInformationMessage(nls.localize('background_task_started'));
});
yield * performBackgroundTask();
// WRONG - Blocks unnecessarily
yield * Effect.promise(() => vscode.window.showInformationMessage(nls.localize('background_task_started')));
// WRONG - Direct call in Effect.gen
yield *
Effect.gen(function* () {
await vscode.window.showErrorMessage('Error'); // Type error
});
showInformationMessage: Success, info, non-criticalshowWarningMessage: Warnings, recoverable errors, user decisionsshowErrorMessage: Errors, failures, critical issuesawait vscode.window.showInformationMessage(nls.localize('retrieve_completed'));
await vscode.window.showWarningMessage(nls.localize('unsaved_changes'));
await vscode.window.showErrorMessage(nls.localize('retrieve_failed', errorMessage));
// Modal with detail (detail only shown for modal)
await vscode.window.showWarningMessage(
nls.localize('destructive_action_warning'),
{ modal: true, detail: nls.localize('destructive_action_detail') },
nls.localize('confirm')
);
Note: VS Code automatically adds a 'Cancel' button to modal dialogs. Do not add an explicit nls.localize('cancel_button') as an item when modal: true. Dismissing the dialog (via 'Cancel' or ESC) returns undefined.
modal?: boolean - System modal dialog, blocks interactiondetail?: string - Extra text (modal only)Strings or MessageItem objects:
// String buttons (prefer)
const result = await vscode.window.showWarningMessage(
nls.localize('confirm_action'),
nls.localize('yes'),
nls.localize('no')
);
// result: string | undefined
// MessageItem (for modal ESC handling)
const result = await vscode.window.showWarningMessage(
nls.localize('confirm_action'),
{ modal: true },
{ title: nls.localize('yes'), isCloseAffordance: false },
{ title: nls.localize('no'), isCloseAffordance: true }
);
// result: MessageItem | undefined
isCloseAffordance: true = button handles ESC. Modal-only. Modals auto-add Cancel; use this to control which custom button handles ESC.
// Fire-and-forget
if (hasErrors) {
void vscode.window.showErrorMessage(nls.localize('operation_completed_with_errors'));
} else {
void vscode.window.showInformationMessage(nls.localize('operation_completed_successfully'));
}
import { Effect } from 'effect';
const confirm =
yield *
Effect.promise(() =>
vscode.window.showWarningMessage(
nls.localize('confirm_destructive_action'),
nls.localize('proceed_button')
)
);
if (confirm === nls.localize('proceed_button')) {
yield * performDestructiveAction();
}
no-vscode-message-literals enforces:
nls.localize() callsshowInformationMessage, showWarningMessage, showErrorMessageRun npm run lint before committing.