Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add LSP server #2662

Closed
wants to merge 80 commits into from
Closed

Add LSP server #2662

wants to merge 80 commits into from

Conversation

jchadwick-buf
Copy link
Member

Passes tests and seems to work so far, unimplemented APIs aside. Source code is partially reorganized to try to be a bit closer to the rest of Buf, but there's plenty that could still be done. We'll probably need to work out how much of that should block.

P.S.: I think the path handling will need to be cleaned up for Windows to work fully. Have yet to test this.

Copy link
Member

@bufdev bufdev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking really good!

I can't comment, but why is there a protovalidate.zip checked in?

wellKnownTypesDescriptorProtoPath = normalpath.Join("google", "protobuf", "descriptor.proto")
// v3WellKnownTypesCacheRelDirPath is the relative path to the cache directory for materialized
// well-known types .proto files.
v3WellKnownTypesCacheRelDirPath = normalpath.Join("v3", "wkt")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I talked to @Alfus about this, but this implies it's the same cache directory as the module cache - is that correct? If so, this should be in a different location - buf lsp should not modify the module cache. We could have $BUF_CACHE_DIR/lsp/wkt/WKT_VERSION as an example

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Putting the version there as a subdirectory seems like a good idea, though I don't see an obvious version in the generated datawkt package. Digest can easily work if that's sufficient/reasonable, though.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(For now I've addressed this by adding the digest of the wkt module into the resulting path.)

@jchadwick-buf
Copy link
Member Author

Looking really good!

I can't comment, but why is there a protovalidate.zip checked in?

It's a terrible hack. Since we can't fetch modules yet due to missing APIs, the test literally pulls the zip as file data into an omni provider.

Obviously, it would be better to get rid of this. Any opinion on how? I think the most obvious paths forward are:

  • Remove dependency and allow it to be invalid. The LSP tests will still run, but some of the tests will need to be removed at least until fetching dependencies works.
  • Vendor protovalidate some other way. I don't have a huge opinion on how if so, the zip thing was just a very quick hack.
  • Adjust the tests/buftest to not depend on protovalidate to begin with. Fine with me, although that will mean we're not really testing dependencies outside of wkt. This might be OK since dependencies are mostly abstracted from the LSP.

@bufdev
Copy link
Member

bufdev commented Dec 13, 2023

I would just check in protovalidate as individual files, not as a zip file - we do this in other places too, theres not many files. ie just explode the zip file into its constituent files and check those in.

@jchadwick-buf
Copy link
Member Author

Works for me, fixed.

@jchadwick-buf
Copy link
Member Author

Do let me know if there's any more work you think I should take a look at on this. For now, I'm at a bit of a stopping point as everything I'm able to test seems to work as expected and I think most of the low hanging fruit for cleaning up the code to Buf's standards/style are taken care of.

Copy link
Member

@bufdev bufdev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leaving code organization alone for now, but some structural questions. I believe most of these are for @Alfus and not @jchadwick-buf but both feel free to chime in here.

if err != nil {
return nil, err
}
omniProvider, err := bufmoduletesting.NewOmniProvider(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're providing protovalidate via this OmniProvider, why do we still need to depend on it via a BSR dependency in buftest? Is there some functionality under the hood we are testing? It's not immediately apparent to me that, if the *server is using the controller, which itself is just depending on the ModuleKeyProvider/ModuleDataProvider given via OmniProvider, why we also need to have a hard dependency on buf.build here.

If not, we could get rid of buftest entirely, and move all the lsp testing code into testdata local to this package.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, SGTM. Now buftest is no more, and I've reverted the changes made to the proto directory as well.

private/buf/buflsp/buflsp.go Outdated Show resolved Hide resolved
if entry, ok := buflsp.fileCache[event.Name]; ok {
if entry.moduleSet != nil {
if err := buflsp.refreshImage(context.Background(), entry.moduleSet, entry.bucket); err != nil {
buflsp.logger.Sugar().Errorf("refreshImage error: %s", err)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be displayed to users, we should make sure this error is meaningful, which I don't think it is if we are referencing an internal method refreshImage.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How should errors that have no one to report them to be handled in general? This can probably just be removed

var err error
workspace, err := s.controller.GetWorkspace(ctx, params.TextDocument.URI.Filename())
if err != nil {
s.logger.Warn("could not determine workspace", zap.Error(err))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be displayed to the user, same comment above.

}

// Create a new file entry for the file
entry, err := s.createFileEntry(ctx, params.TextDocument, moduleSet)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moduleSet can be nil, are we making sure that createFileEntry is documented that one of its parameters may be nil?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've eliminated the intentionally-nil module set pointers.

private/buf/buflsp/buflsp.go Outdated Show resolved Hide resolved
bucket = s.wellKnownTypesBucket
file, err = bucket.GetFile(ctx, path)
if err != nil {
s.logger.Warn("could not resolve import", zap.String("path", path))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why aren't we returning this error? We generally never want to using logging as a means of error propagation unless absolutely necessary.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is going to be necessary to swallow some errors at some point because the LSP should provide some functionality even when the source code is partially broken, since the LSP will necessarily see source code as it is being typed. In this case, it doesn't actually matter since we bail out earlier in processText anyway, so there's really no point in swallowing this error, so now it does not do that.

workspace, err := s.controller.GetWorkspace(ctx, params.TextDocument.URI.Filename())
if err != nil {
s.logger.Warn("could not determine workspace", zap.Error(err))
// Continue anyways if this fails.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the reason for this is that we can still provide useful features even if we can't get a workspace.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous statement (that we still provide useful features even without a workspace) is still true, but this hack is no longer necessary as I've deferred workspace resolution until later, so we don't need to swallow this error here anymore.

private/buf/buflsp/buflsp.go Outdated Show resolved Hide resolved
@bufdev
Copy link
Member

bufdev commented Feb 12, 2024

Pushed this work to https://github.com/bufbuild/buf/tree/do-not-delete-buf-lsp-merge for long-term storage for now. We talked offline and agreed we need to rework this, which we hope to pick up relatively soon. Closing this PR as it is.

@bufdev bufdev closed this Feb 12, 2024
@jpaju
Copy link

jpaju commented Feb 21, 2024

I'd love to see the LSP released someday 🚀

@bufdev bufdev deleted the jchadwick/buf-lsp-merge branch March 19, 2024 21:12
@fira42073
Copy link

Hey! I wonder if there are any updates here? Buf is the de-facto standard for proto generation for many teams, and it would be nice to have a compatible lsp as well. There are other solutions available, but they usually lack maintenance and features. Anyway, it would be awesome if this would be revived C:
Thanks for all of your work!

@bufdev
Copy link
Member

bufdev commented Aug 27, 2024

We're reviving this and working on it soon, cc @mcy

@juanpmarin
Copy link

Is there a place to follow the progress on the server?

@jpaju
Copy link

jpaju commented Oct 12, 2024

The first version of the LSP is already released: #3316. I guess you can follow the PRs in this repo to see the progress

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants