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

@typefox/monaco-editor-react - multiple files, one lsp websocket connection #652

Closed
apathoid opened this issue May 4, 2024 · 5 comments
Closed

Comments

@apathoid
Copy link

apathoid commented May 4, 2024

Greetings!

I have a problem with @typefox/monaco-editor-react, that I can't make it work with multiple opened files that share one WS connection to a lsp server. Whenever I open the second file it tries to initialize already opened connection and I get this in the console:

image

after that the popup with suggestions starts to display "loading" and nothing more in both editors. Moreover onTextChanged callback is triggered for the first editor exclusively. The lsp connection looks fine and continues to send/receive requests though.

So the question: is it even possible to use MonacoEditorReactComp so that it can handle one connection for multiple files?

I use custom SharedWorker that initializes WS connection and serves as a proxy between the lsp server and the language client itself:

  • worker.ts
declare const self: SharedWorkerGlobalScope;

const connectedPorts = new Set<MessagePort>();

const ws = new WebSocket('wss://address/to/lsp');
ws.onmessage = e => connectedPorts.forEach(port => port.postMessage(JSON.parse(e.data)));


self.addEventListener('connect', e => {
    const port = e.ports[0];
    connectedPorts.add(port);

    port.onmessage = e => {
        ws.send(JSON.stringify(e.data));
    };
});


export {};
  • index.ts file with the worker instantiation
export default new SharedWorker(new URL('./worker.ts', import.meta.url), { type: 'module', name: 'Julia LSP Server' });
  • user-config.ts
import * as vscode from 'vscode';
import lspWorker from './lsp-worker';


export const userConfig = {
    languageClientConfig: {
        options: {
            name: 'Julia Language Server',
            $type: 'WorkerDirect',
            worker: new Worker(new URL('', import.meta.url), { type: 'module' }),
            messagePort: lspWorker.port
        },
        clientOptions: {
            documentSelector: ['julia'],
            workspaceFolder: {
                index: 0,
                name: 'workspace',
                uri: vscode.Uri.parse('/workspace')
            }
        }
    },
    wrapperConfig: {
        editorAppConfig: {
            languageId: 'julia',
            codeUri: `/workspace/${fileName}.jl`
        }
    }
};

Have to say that if I unmount a component with the first editor before mounting the second one it works fine. But I need to keep them opened in order to preserve their contexts in case the user walks through the tabs with these editors.

I tried to search the answer in the examples folder and here, in issues, but had no luck. Thanks in advance.

@kaisalmen
Copy link
Collaborator

Hi @apathoid thank you for reporting this. Can you share a repository, so I can re-produce this?

Have you tried this without the proxy (reduce the complexity first and see if it works)? How do you open the second file?
When you use a worker, there is no need for a web-socket connection, btw.

@apathoid
Copy link
Author

apathoid commented May 6, 2024

I have a remote lsp server that is maintained by our backend team. This is the reason why I need a WS connection (if I understood your last statement correctly). I establish it inside a SharedWorker, because I want to be able to use the same WS connection across multiple editors (and browser tabs) with the same language.

Here is the example of what I'm trying to achieve. There is no real lsp server there, but the idea and behavior are nearly identical to what I have in my real app.

If you create one file you'll see the 'initialize' message in the dev tools and then, when you open the second file, you'll get the exactly same message. In the real app it looks like this:

when I open the first file
when I open the second file

Also I can't open two editors simultaneously: they just double requests and only one of them remains functioning (the second one doesn't trigger onTextChanged callback):

@CGNonofr
Copy link
Collaborator

CGNonofr commented May 6, 2024

What you are trying to do is plugging multiple clients on the same language server connection, which is not supported out of the box.

You may need something like https://github.com/CodinGame/languageserver-mutualized

You can probably run it in a shared worker even though it was designed to run in node

@apathoid
Copy link
Author

apathoid commented May 7, 2024

@CGNonofr, thank you. I'll give it a try

@kaisalmen
Copy link
Collaborator

Closing this as way forward was proposed.

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

No branches or pull requests

3 participants