This is part of #41882 and tracks callers of registerDocumentFormattingEditProvider and registerDocumentRangeFormattingEditProvider that don't dispose their registrations when being disabled.
For VSCode calling registerDocument[Range]?FormattingEditProvider adds a formatter, that for instance drives enablement of context menu actions, like "Format Selection" or "Format Document". Most formatters follow our recommendation of having a setting to enable/disable them. However, some formatters don't unregister when being disabled, returning a null/empty-edit instead. That's problematic, because it doesn't allow VSCode to update the UI correctly (e.g hiding the "Format Document" action) and it contributes to the problem of multiple formatters (#41882). A disabled, but registered formatter is still a formatter in VSCode terms, meaning VSCode will continue to ask it for formatting edits and VSCode will continue to have multiple formatter available for a language.
A correct formatter unregisters when being disabled, as shown in the sample below. The following list is composed of those formatters that conflict most often:
The snippet below check with vsocde.workspace.getConfiguration() if the formatter is enabled and re-checks whenever the setting has changes (see vscode.workspace.onDidChangeConfiguration). Listening to the config-change is important for a smooth formatter update, without a restart.
// document formatter
const formatter: vscode.DocumentFormattingEditProvider = {
provideDocumentFormattingEdits(document: vscode.TextDocument): vscode.TextEdit[] {
const firstLine = document.lineAt(0);
if (firstLine.text !== '42') {
return [vscode.TextEdit.insert(firstLine.range.start, '42\n')];
}
}
};
// have a function that adds/removes the formatter based
// on a configuration setting
let registration: vscode.Disposable | undefined;
function registerFormatterIfEnabled() {
const isEnabled = vscode.workspace.getConfiguration().get('fooLang.formatter.enabled', true);
if (isEnabled && !registration) {
// 👍good - only enabled formatter is added
registration = vscode.languages.registerDocumentFormattingEditProvider('fooLang', formatter);
} else if (!isEnabled && registration) {
// 👍good - disabled formatter is removed
registration.dispose();
registration = undefined;
}
}
// register at activate-time
registerFormatterIfEnabled();
// add/remove formatter when config changes
vscode.workspace.onDidChangeConfiguration(event => {
if (event.affectsConfiguration('fooLang.formatter.enabled')) {
registerFormatterIfEnabled();
}
});
This is part of #41882 and tracks callers of
registerDocumentFormattingEditProviderandregisterDocumentRangeFormattingEditProviderthat don't dispose their registrations when being disabled.For VSCode calling
registerDocument[Range]?FormattingEditProvideradds a formatter, that for instance drives enablement of context menu actions, like "Format Selection" or "Format Document". Most formatters follow our recommendation of having a setting to enable/disable them. However, some formatters don't unregister when being disabled, returning a null/empty-edit instead. That's problematic, because it doesn't allow VSCode to update the UI correctly (e.g hiding the "Format Document" action) and it contributes to the problem of multiple formatters (#41882). A disabled, but registered formatter is still a formatter in VSCode terms, meaning VSCode will continue to ask it for formatting edits and VSCode will continue to have multiple formatter available for a language.A correct formatter unregisters when being disabled, as shown in the sample below. The following list is composed of those formatters that conflict most often:
The snippet below check with
vsocde.workspace.getConfiguration()if the formatter is enabled and re-checks whenever the setting has changes (seevscode.workspace.onDidChangeConfiguration). Listening to the config-change is important for a smooth formatter update, without a restart.