Closed jrieken closed 5 years ago
@dbaeumer can you add a sample how to unregister a formatter in LSP land?
Will do https://github.com/vuejs/vetur/issues/1121 for March.
You need to register a formatter dynamically to be able to unregister it. It can not be registered via the return value from the initialize call. So instead of something like this:
let result: InitializeResult = {
capabilities: {
textDocumentSync: TextDocumentSyncKind.Full,
documentFormattingProvider: true
}
};
you need to do something like this:
let registration: Disposable | undefined;
connection.client.register(DocumentFormattingRequest.type, {
documentSelector: ['javascript']
}).then((disposable) => {
registration = disposable;
});
To unregister you call registration.dispose();
@jrieken There was a note here about providing the setting name to VS Code to do this:
https://github.com/Microsoft/vscode/issues/41882#issuecomment-451221511
Is that still an option? It seems simpler than having to implement the code above for every extension. It also gets a bit complicated than the above if you register multiple document modes dynamically, and have document + onType formatters. And also, I think the above code isn't adding the subscription to context.subscriptions
(is this required? I've been doing it for everything I register, even though it seems like VS Code should be able to track them itself).
Does it make sense that leaving the disabled formatter registered? Is it possible that vscode unregisters the formatter when it is disabled automatically?
@multics Two times "no". A disabled formatter must unregister so that it doesn't show in the UX anymore (see https://github.com/Microsoft/vscode/issues/70314#issue-420052214). Also, it's not possible to unregister them for us because we don't know the setting an extension uses. That means the responsibility is with the formatter
Couldn't VS Code keep all registered formatters, but skip over them when formatting if their corresponding setting is disabled?
It doesn't matter to me now, I've already done my work - but it feels like it'd be a much simpler API than each extension having to do its own housekeeping.
but skip over them when formatting if their corresponding setting is disabled?
And how would vscode know those settings and how interpret them?
@jrieken you posted a comment here:
https://github.com/Microsoft/vscode/issues/41882#issuecomment-451221511
which sounded like it was the plan. We pass a string setting name to VS Code and it toggles the formatter based on that setting (which would be a boolean). I honestly thought that was the plan (and couldn't see any obvious reason why that was no longer the case), which is why I was surprised it wasn't so trivial when I came to do it.
Please read the whole thread: https://github.com/Microsoft/vscode/issues/41882#issuecomment-451383501
Aha! Apologies, I thought I'd read the whole thread, but I may have missed some comments collapsed by GH. Makes sense now, thanks!
What happens if an extension with a registered formatter is literally disabled or uninstalled without restart?
I added vetur.format.enable
, will be released in 0.17.1.
What happens if an extension with a registered formatter is literally disabled or uninstalled without restart?
In that case the deactivate
function of that extension is being called. If the extension did everything right, e.g. manages its registrations correctly than the formatter is unregistered.
Some of the reasons people didn't use dynamic registration are probably:
I created https://github.com/Microsoft/vscode-docs/issues/2522 for that.
However, if all formatters should have a boolean setting for enablement / disablement, do we still consider adding API to simplify the registration?
In LSP it could look like:
let result: InitializeResult = {
capabilities: {
documentFormattingProvider: {
enablementSetting: 'prettier.enable'
}
}
}
I was just trying to run some of my tests against LSP and discovered my setting to disable the formatter didn't work. Is there a way to handle this? @octref mentions LSP above but I'm not sure I understand the snippet. If I understand correctly, we need to use a VS Code setting to tell the LSP client not to call formatting on the server (the server doesn't really need to know, it just won't get called for formatting)?
@DanTup Above was just a suggestion how it could look in LSP.
my setting to disable the formatter didn't work.
You should:
--data-dir
and include settings.json
. Example@octref I badly described the issue - my test highlighted that this setting doesn't work when using LSP (so if I migrate users to LSP, the setting will seem broken), I wasn't specifically trying to fix the tests.
I'm not sure how best to make that setting actually affect the LSP server. I guess I could pass it in the initialisation options and then have the server pretend it doesn't support it but that seems weird (the client shouldn't tell the server what it supports, and it seems a fairly VS-Code-specific way to handle it).
It seems like maybe the LSP client should be able to handle this (for ex. if we can tell it to disable/re-enable the formatter?).
That said, I wonder if this is necessary now that VS Code can prompt for multiple formatters anyway. Maybe it's reasonable to just ditch the setting entirely for both LSP and non-LSP?
I'm not sure how best to make that setting actually affect the LSP server.
https://github.com/microsoft/vscode/issues/70314#issuecomment-472336416 https://github.com/vuejs/vetur/commit/061e4cfe27bd896ffb017a5b6080dbe177264144
That said, I wonder if this is necessary now that VS Code can prompt for multiple formatters anyway. Maybe it's reasonable to just ditch the setting entirely for both LSP and non-LSP?
It's better to provide an option so users can use other features of your extension and not having to choose formatter each time.
@octref aha! I'd overlooked that - I think that'll work fine - thanks! 👍
This is part of #41882 and tracks callers of
registerDocumentFormattingEditProvider
andregisterDocumentRangeFormattingEditProvider
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:
[x] vscode.html-language-features: ✅ no change needed
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.