Description
Hi, I am using monaco-editor & monaco-languageclient (to connect to LSPs) with vscode-json-languageserver - which uses vscode-json-languageservice for intellisense for .json
& .jsonc
files in the text editor desktop app I am building, the issue is the vscode-json-languageserver doesn't work at all for tsconfig (jsonc) files and treats them as normal json
files and it also doesn't provide hover suggestions for normal json files such as package.json
I have asked ChatGPT & Gemini and the suggestions I got was the schema
configuration and which I have applied their suggestions but couldn't get it to work
The project environment
- ElectronForge
- React JS
- TypeScript
- vite
- monaco-editor
- monaco-languageclient
I am running thevscode-json-languageserver
in a child process (programmatically) withvscode-jsonrpc/node
to handle the input and output stream and sending messages between the client and the server over electronjs IPC
This is my monaco-languageclient code
//...
async configure_lc (): Promise<any> {
this.lang_client = this.createLanguageClient({
reader: {
onClose: () => {
console.log("LP client closed");
},
onError: () => {
console.log("reader closed");
},
onPartialMessage: (data: any) => {
console.log("onPartialMessage", data);
},
listen: (cb: Function) => {
console.log("reader onMessage", typeof cb);
this.winEvCallbackRef = (e: Event & {detail: any}) => {
console.log("window got event", e.detail);
cb(e.detail);
}
window.addEventListener(`lsp-${this.lang_id}-ev`, this.winEvCallbackRef)
},
dispose: () => {
console.log("reader disposed");
},
},
writer: {
onClose: () => {
console.log("LP client writer closed");
},
onError: () => {
console.log("writer closed");
},
write: (msg: any) => {
console.log("writer onMessage", msg);
window.mp_electron.lsp_msg(msg, this.lang_id)
return Promise.resolve();
},
dispose: () => {
console.log("reader disposed");
},
},
} as any, this.rootPath);
if(this.lang_is_running(this.lang_id)) return;
this.lang_client.start()
.then((v) => {
this.running_language = this.lang_id
})
.catch((e) => {
console.log("LC connect failed", e);
});
};
createLanguageClient (messageTransports: MessageTransports, rootPath: string): MonacoLanguageClient {
return new MonacoLanguageClient({
name: LSClientHandler.textToTitleCase(this.lang_id) + ' Language Server',
clientOptions: {
documentSelector: [this.original_lang_id],
errorHandler: {
error: () => ({ action: ErrorAction.Continue }),
closed: () => ({ action: CloseAction.DoNotRestart })
},
workspaceFolder: {
index: 0,
name: rootPath,
uri: monaco.Uri.parse(rootPath)
}
},
messageTransports: messageTransports,
// @ts-ignore
connectionProvider: {
get: async (_encoding: string) => messageTransports
}
});
}
//...
and this is my LSP code
console.log("running lsp data", lsp_proc, "languages::", running_languages);
if (!(lang_id in lang_servers)) return;
if (running_languages.includes(lang_id)) {
lsp_proc[lang_id].kill();
};
const runner = "node";
lsp_proc[lang_id] = cp.spawn(runner, [path.resolve(__dirname, lang_servers[lang_id as keyof typeof lang_servers]), '--stdio'], )
stream_reader[lang_id] = new StreamMessageReader(lsp_proc[lang_id].stdout);
stream_writer[lang_id] = new StreamMessageWriter(lsp_proc[lang_id].stdin);
ipcMain.on(`lsp-${lang_id}-message`, async (ev, data) => {
await stream_writer[lang_id].write(data)
.catch(err => {
console.log("error occured while writing data to stdout in msg write", err);
});
})
stream_reader[lang_id].listen((msg) => {
mainWindow.webContents.send(`lsp-${lang_id}-ev`, {data: msg, lang_id});
});
lsp_proc[lang_id].on('spawn', () => {
console.log("lsp proc spawned");
running_languages.push(lang_id);
})
lsp_proc[lang_id].on('close', (code) => {
console.log("lsp proc closed", code);
running_languages.splice(running_languages.indexOf(lang_id), 1);
})
Please what I'm I missing or doing wrong?
Based on suggestions from ChatGPT and Gemini this is what I've tried but didn't have any effects
Description: I tried to send a json/schemaAssociations
notification to the json LSP after initialization but did not make any effects
//...
this.lang_client.start()
.then((v) => {
if(this.original_lang_id == 'jsonc') {
this.lang_client.sendNotification('json/schemaAssociations', {
"http": {
"proxy": "",
"proxyStrictSSL": false
},
"json": {
"format": {
"enable": true
},
"schemas": [
{
"fileMatch": ['tsconfig.json', 'tsconfig.*.json'],
"url": "https://json.schemastore.org/tsconfig.json",
}
]
}
})
}
})
.catch((e) => {
console.log("LC connect failed", e);
});
//...
Thank you