I currently have a language server that provides SQL autocompletion for keywords, functions, tables, columns etc...
The language server is running on the back-end and it's providing autocompletion based on the client's requests. On the front-end I have a react app with the following component:
import React, { Component } from 'react';
import * as monaco from 'monaco-editor';
import { listen } from '@codingame/monaco-jsonrpc';
import {
MonacoLanguageClient,
MonacoServices,
createConnection,
MessageConnection,
} from "monaco-languageclient";
import ReconnectingWebSocket from "reconnecting-websocket";
import { URI } from 'vscode-uri';
const LANGUAGE_ID = 'sql';
let languageClient: MonacoLanguageClient;
class MonacoEditor extends Component {
componentDidMount() {
const {
wordWrap,
showLineNumbers,
readOnly,
id
} = this.props;
// creating the editor
this.editor = monaco.editor.create(document.getElementById(id) as HTMLElement, {
model: monaco.editor.createModel('', LANGUAGE_ID, monaco.Uri.parse(`inmemory://model${id}.sql`)),
minimap: { enabled: false },
glyphMargin: true,
lightbulb: {
enabled: true
},
language: LANGUAGE_ID,
fontSize: 14,
matchBrackets: 'always',
wordWrap: wordWrap ? 'on' : 'off',
lineNumbers: showLineNumbers ? 'on' : 'off',
readOnly,
scrollBeyondLastLine: false
});
// installing the language client
MonacoServices.install(monaco);
function createLanguageClient(
connection: MessageConnection
): MonacoLanguageClient {
return new MonacoLanguageClient({
name: "SQL Language Server MonacoClient",
clientOptions: {
documentSelector: ["sql"],
workspaceFolder: {
uri: URI.file('/opt/monaco_editor'),
name: 'workspace',
index: 0
}
},
connectionProvider: {
get: (errorHandler, closeHandler) => {
return Promise.resolve(
createConnection(connection, errorHandler, closeHandler)
);
},
},
});
}
function createWebSocket(url: string): ReconnectingWebSocket {
const socketOptions = {
maxReconnectionDelay: 10000,
minReconnectionDelay: 1000,
reconnectionDelayGrowFactor: 1.3,
connectionTimeout: 10000,
maxRetries: Infinity,
debug: false,
};
return new ReconnectingWebSocket(url, [], socketOptions);
}
const URL = "ws://localhost:8080";
const webSocket = createWebSocket(URL) as WebSocket;
listen({
webSocket,
onConnection: (connection) => {
languageClient = createLanguageClient(connection);
const disposable = languageClient.start();
connection.onClose(() => disposable.dispose());
},
});
}
render() {
const { id } = this.props;
return (
<div>
<h1 style={{textAlign: 'center'}}>SQL Syntax checking</h1>
<div id={id} style={{height: '600px', width: '100%' }} />
</div>);
}
}
export default MonacoEditor;
What I want to achieve is having multiple editor instances on the same page. However, when I try to do that I get duplicate keywords in the completion suggestions (see below).
I tried to do some research but I couldn't find anything that works for my case.
As you can see from the code I don't have any monaco.languages.registerCompletionItemProvider()
that I could dispose. All the autocompletion data is sent by the back-end.
Is there any workaround to fix this issue?