Skip to content
This repository has been archived by the owner on Jul 15, 2023. It is now read-only.

Avoid registering more than 1 formatting provider at a time #2446

Closed
ramya-rao-a opened this issue Apr 17, 2019 · 27 comments
Closed

Avoid registering more than 1 formatting provider at a time #2446

ramya-rao-a opened this issue Apr 17, 2019 · 27 comments
Labels

Comments

@ramya-rao-a
Copy link
Contributor

For details on the issue see microsoft/vscode#72315

We register 2 formatting providers when the language server is enabled, but the format feature from it is disabled.

"go.useLanguageServer": true,
"go.languageServerExperimentalFeatures": {
    "format": false
}

We should avoid doing so, and un-register the provider from the language server in such scenario

@ramya-rao-a
Copy link
Contributor Author

@stamblerre For more context, please see microsoft/vscode#72315 and
microsoft/vscode#70314 (comment).

Can we have gopls skip the registering of the formatter if the user has chosen not to have the formatting feature from gopls?

@stamblerre
Copy link
Contributor

So the solution would be to always register formatting dynamically? How would this work for editors that don't support dynamic registration?

@ramya-rao-a
Copy link
Contributor Author

I am not sure if the editor needs to be aware of the dynamic registration.

@dbaeumer, @octref Can you shed some light here?

@dbaeumer
Copy link
Member

dbaeumer commented Jul 2, 2019

For editors that don't support dynamic registration there is currently no way for them to unregister. All a server can do is to register things statically then.

In general I think that a server should un-register a formatter if it gets disabled.

@stamblerre
Copy link
Contributor

So based on my understanding of microsoft/vscode#70314 (comment), we should check if the client supports dynamic registration, and if not statically register. Otherwise, we should dynamically register only. Is this correct?

@ramya-rao-a
Copy link
Contributor Author

How would you identify whether the editor supports dynamic registration or not?

@dbaeumer
Copy link
Member

dbaeumer commented Jul 3, 2019

@stamblerre yes, that is corrent.
@ramya-rao-a this is advertised in the client capabilities send to the server.

@vincepri
Copy link

vincepri commented Jul 5, 2019

/cc

@ramya-rao-a ramya-rao-a added the upstream-gopls Issue for gopls label Jul 6, 2019
@vincepri
Copy link

vincepri commented Jul 6, 2019

Is there an upstream issue to track this?

@stamblerre
Copy link
Contributor

stamblerre commented Jul 8, 2019

Filed golang/go#32989.

@stamblerre
Copy link
Contributor

@ramya-rao-a: With the fix in https://go-review.googlesource.com/c/tools/+/185244, I have started to see the duplicate formatting provider error. Is there something that needs to be changed on the VSCode-Go end before we can submit this change?

@ramya-rao-a
Copy link
Contributor Author

Are you seeing the duplicate formatting problem even if you have opted into using the format feature from the language server i.e format is true in go.languageServerExperimentalFeatures?

If so, then add a breakpoint at https://github.com/microsoft/vscode-go/blob/0.11.3/src/goMain.ts#L248 and see if vscode-go is registering its own formatter even when you have chosen to use the one from gopls

Also, I believe gopls needs to know when to register the formatting provide and when not to. I am guessing that is where initializationOptions comes into play?

@stamblerre
Copy link
Contributor

The approach we tried for gopls was the one recommended by @dbaeumer - registering dynamically, unless dynamic configuration is not supported (see https://go-review.googlesource.com/c/tools/+/185244).

Based on the linked code, I would guess the VSCode-Go extension needs some additional logic to de-register the default formatting provider if the language server's formatting provider is dynamically registered. In this instance, it registers both providers because the language server sends back false for the DocumentFormattingProvider in the server capabilities.

@vincepri
Copy link

The other question I have is how can we handle the case when format is set to false instead. Can we let users to use goimports/goreturns if they wish to do so? Should gopls skip the dynamic registration in this case?

@ramya-rao-a
Copy link
Contributor Author

ramya-rao-a commented Jul 19, 2019

@stamblerre The Go extension registers the provider because gopls returns true for the DocumentFormattingProvider in the server capabilities

Edit: The Go extension registers its provider as it sees format is set to false in go.languageServerExperimentalFeatures.

image

My settings:

"go.useLanguageServer": true,
"go.languageServerExperimentalFeatures": {
    "format": false
  }
"[go]": {
    "editor.insertSpaces": false,
    "editor.formatOnSave": true,
    "editor.codeActionsOnSave": {
      "source.organizeImports": false
    }

And I have updated to the latest gopls

@vincepri
Copy link

@ramya-rao-a Can you try to use this patch https://go-review.googlesource.com/c/tools/+/185244/5/internal/lsp/general.go to see if the behavior is what you'd expect?

@ramya-rao-a
Copy link
Contributor Author

ramya-rao-a commented Jul 21, 2019

Apologies, the assessment in my earlier comment was wrong, I have crossed it out and updated the scenario where the vscode-go extension would register its formatter which is either when

  • format is set to false in go.languageServerExperimentalFeatures.
  • Or if the language server has not set registered a formatting provider.

Currently, the problem is not that the vscode-go extension is registering the duplicate formatter. The problem is that gopls is not reading go.languageServerExperimentalFeatures to determine whether or not to register the formatter.

The microsoft/vscode#70314 (comment) only talks about half the issue i.e how to unregister a provider

gopls still has to make the call that the user has chosen not to use its formatting feature and so should then either not register its formatter or un-register it

@stamblerre
Copy link
Contributor

Can't VSCode-Go do the configuration handling on its end? Doesn't this handling happen here:

provideDocumentFormattingEdits: (document: vscode.TextDocument, options: FormattingOptions, token: vscode.CancellationToken, next: ProvideDocumentFormattingEditsSignature) => {
?

@stamblerre
Copy link
Contributor

I've been taking a look at this from the VSCode end, and I'm a bit stuck on how this should behave. I thought that the extension could register a formatting provider if the server didn't return DocumentFormattingProvider in its capabilities, and then dispose of that provider if the server dynamically registered formatting.

I tried to implement this via the client.onRequest function, but it seems like that doesn't behave like middleware, and there's no way to actually accept the registration from the language server when using that function. There also doesn't seem to be any way to reject the dynamic formatting registration request when it's sent by the language server or any way to tell the language server not to register formatting.

It's possible I'm completely misunderstanding something, but @dbaeumer's comment (microsoft/vscode#70314 (comment)) shows the behavior of the language server, whereas what we need to do is dispose of a provider when a different provider gets registered.

@ramya-rao-a
Copy link
Contributor Author

I thought that the extension could register a formatting provider if the server didn't return DocumentFormattingProvider in its capabilities, and then dispose of that provider if the server dynamically registered formatting.

How would gopls decide whether or not to register the formatter if it is not able to read the go.languageServerExperimentalFeatures setting?

@stamblerre
Copy link
Contributor

I had hoped that there would be some way for the client to either accept or reject the registration from the language server, but it seems like that's not the case. It seems pretty counter-intuitive to me that the language server should have to be passed settings for which features to register, since to my mind, that's what server and client capabilities are for.

This basically means that, if we want to allow the features of the language server to be configured, we have to expose a setting for each of these features to be enabled or disabled. I'm starting to think that perhaps the language server should really be all-or-nothing--it will be extremely hard to debug if each user has a different configuration. The experience with the language server should be as simple as turning it on.

My proposal is that we remove the ability to configure these features entirely. I understand that there will be friction, as some users have different preferences. Ideally, this will cause people to file more feature requests, and then the language server can be improved to fit the users' needs. These configurations are just masking the problem.

/cc @ianthehat

@stamblerre
Copy link
Contributor

I think that the ultimate resolution to this issue would be to remove the go.experimentalLanguageServerFeatures setting for formatting so that users of gopls would be required to use gopls's formatting. I believe the that the main concern with this would be that gopls doesn't provide the features of goreturns, which some users prefer as a format tool. A solution would be for gopls to support features offered by goreturns (perhaps as code action quick fixes).

@ramya-rao-a: Are there any other concerns here?

@ramya-rao-a
Copy link
Contributor Author

I am ok with the approach of removing format from go.experimentalLanguageServerFeatures.
The only concern is that we should resolve the formatting issues that people have currently reported before doing that.

@stamblerre
Copy link
Contributor

Absolutely. We can wait on it until such a time as there are no issues with gopls formatting.

@stamblerre
Copy link
Contributor

stamblerre commented Apr 5, 2020

The majority of the issues with gopls formatting seem to have been resolved, and gopls will have goreturns-type functionality in the next release (https://golang.org/cl/224960). Do you think we can remove this setting in the next version of the extension (meaning 0.15, not 0.14 since that will be coming out soon)?

If we're ready to that, I can add that to #3156.

@ramya-rao-a
Copy link
Contributor Author

Sure, that works

@ramya-rao-a
Copy link
Contributor Author

ramya-rao-a commented Apr 26, 2020

Closing this issue as with #3156 in the upcoming version of the extension, we drop the support for falling back to the extension's format feature when using the language server. So, there wouldnt be multiple formatting providers being registered at the same time

@vscodebot vscodebot bot locked and limited conversation to collaborators Jun 10, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

4 participants