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

Migrate to LSP #7

Open
PolyMeilex opened this issue Sep 16, 2021 · 6 comments
Open

Migrate to LSP #7

PolyMeilex opened this issue Sep 16, 2021 · 6 comments
Labels
enhancement New feature or request

Comments

@PolyMeilex
Copy link
Owner

PolyMeilex commented Sep 16, 2021

We should probably migrate the server to LSP, so we can support more editors instead of being vs-code specific.

Potentially useful crates:

Notes:

@PolyMeilex PolyMeilex added the enhancement New feature or request label Sep 16, 2021
@cactusdualcore
Copy link

cactusdualcore commented Jul 27, 2023

I think the tower-lsp crate might be potentially useful too. It uses lsp-types internally, but includes much functionality of an lsp server already, like concurrently handling incoming requests and routing, than lsp-server.
This uses tokio already so tower seems like a natural choice to me.

@cactusdualcore
Copy link

cactusdualcore commented Jul 27, 2023

I'd like to quickly show tower-lsp here

// this is shared data for handlers e.g. config. It must be thread safe
pub struct MyLanguageServer { client: Client /* other fields can go here */ }

The LanguageServer trait is how to respond to requests

#[tower_lsp::async_trait]
impl LanguageServer for MyLanguageServer {
    // `InitializeParams` includes client-side configs among other things.
    // The crate passes immutable refs, so working with `self` is inconvenient, because it requires
    // thread-safe (`Sync`) interior mutability. Both `tokio` and the `once_cell` crate have a `OnceCell`
    // which I find make it easier. I prefer the latter because of its cleaner interface.
    async fn initialize(&self, params: InitializeParams) -> Result<InitializeResult> {
        Ok(InitializeResult::default())
    }

    // called upon requesting graceful shut down. This is different from process exit.
    async fn shutdown(&self) -> Result<()> { Ok(()) }

    // LSP events are modeled as functions on this trait, which makes implementing them straightforward,
    // but all references are immutable so they have have the same inconveniences as `initialize` 
    async fn did_open(&self, params: DidOpenTextDocumentParams) {}
}

This is how to start the server

let rt = tokio::runtime::Runtime::new().unwrap();
rt.block_on(async {
    let stdin = tokio::io::stdin();
    let stdout = tokio::io::stdout();
    let (service, socket) = LspService::new(MyLanguageServer::new); // MyLanguageServer::new(Client) -> Self
    Server::new(stdin, stdout, socket).serve(service).await;
})

@Runi-c
Copy link

Runi-c commented Feb 20, 2024

@PolyMeilex Would you be open to a PR migrating the current functionality of cargo-wgsl to LSP using tower-lsp as suggested above? Potentially with a companion PR for vscode-wgsl to support it as well?

@PolyMeilex
Copy link
Owner Author

Sure, as long as we have vscode PR for that as well, my implementation got stuck on that as far as I remember, as I was too lazy to port the extension 😄

I did not see the need for tower-lsp when doing my impl, but if that makes your life or code simpler, then sure feel free to go ahead with that.

@cactusdualcore
Copy link

tower-lsp is great because it requires barely any boilerplate. So less code to maintain.

@cactusdualcore
Copy link

Considering that the vsc extension might need a significant rewrite, it might be a good idea to "move" it into this repo as well. Might make versioning and updating easier.

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

No branches or pull requests

3 participants