Web workers for the lsp servers (#2136)
* put the lsps into a web worker Signed-off-by: Jess Frazelle <github@jessfraz.com> * remove extraneous logs Signed-off-by: Jess Frazelle <github@jessfraz.com> * remove trash toml lib Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixes Signed-off-by: Jess Frazelle <github@jessfraz.com> * less logs Signed-off-by: Jess Frazelle <github@jessfraz.com> * less logs Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixups Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixes for tests Signed-off-by: Jess Frazelle <github@jessfraz.com> * for playwright go back to the shitty lib Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix Signed-off-by: Jess Frazelle <github@jessfraz.com> --------- Signed-off-by: Jess Frazelle <github@jessfraz.com>
This commit is contained in:
@ -2,9 +2,8 @@ import { LanguageServerClient } from 'editor/plugins/lsp'
|
||||
import type * as LSP from 'vscode-languageserver-protocol'
|
||||
import React, { createContext, useMemo, useEffect, useContext } from 'react'
|
||||
import { FromServer, IntoServer } from 'editor/plugins/lsp/codec'
|
||||
import Server from '../editor/plugins/lsp/server'
|
||||
import Client from '../editor/plugins/lsp/client'
|
||||
import { TEST } from 'env'
|
||||
import { DEV, TEST } from 'env'
|
||||
import kclLanguage from 'editor/plugins/lsp/kcl/language'
|
||||
import { copilotPlugin } from 'editor/plugins/lsp/copilot'
|
||||
import { useStore } from 'useStore'
|
||||
@ -15,6 +14,13 @@ import { useNavigate } from 'react-router-dom'
|
||||
import { paths } from 'lib/paths'
|
||||
import { FileEntry } from 'lib/types'
|
||||
import { NetworkHealthState, useNetworkStatus } from './NetworkHealthIndicator'
|
||||
import Worker from 'editor/plugins/lsp/worker.ts?worker'
|
||||
import {
|
||||
LspWorkerEventType,
|
||||
KclWorkerOptions,
|
||||
CopilotWorkerOptions,
|
||||
LspWorker,
|
||||
} from 'editor/plugins/lsp/types'
|
||||
|
||||
const DEFAULT_FILE_NAME: string = 'main.kcl'
|
||||
|
||||
@ -87,20 +93,34 @@ export const LspProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
// But the server happens async so we break this into two parts.
|
||||
// Below is the client and server promise.
|
||||
const { lspClient: kclLspClient } = useMemo(() => {
|
||||
const intoServer: IntoServer = new IntoServer()
|
||||
const fromServer: FromServer = FromServer.create()
|
||||
const client = new Client(fromServer, intoServer)
|
||||
if (!TEST) {
|
||||
Server.initialize(intoServer, fromServer).then((lspServer) => {
|
||||
lspServer.start('kcl', token)
|
||||
setIsKclLspServerReady(true)
|
||||
})
|
||||
if (!token || token === '' || TEST) {
|
||||
return { lspClient: null }
|
||||
}
|
||||
|
||||
const lspClient = new LanguageServerClient({ client, name: 'kcl' })
|
||||
const lspWorker = new Worker({ name: 'kcl' })
|
||||
const initEvent: KclWorkerOptions = {
|
||||
token: token,
|
||||
baseUnit: defaultUnit.current,
|
||||
devMode: DEV,
|
||||
}
|
||||
lspWorker.postMessage({
|
||||
worker: LspWorker.Kcl,
|
||||
eventType: LspWorkerEventType.Init,
|
||||
eventData: initEvent,
|
||||
})
|
||||
lspWorker.onmessage = function (e) {
|
||||
fromServer.add(e.data)
|
||||
}
|
||||
|
||||
const intoServer: IntoServer = new IntoServer(LspWorker.Kcl, lspWorker)
|
||||
const fromServer: FromServer = FromServer.create()
|
||||
const client = new Client(fromServer, intoServer)
|
||||
|
||||
setIsKclLspServerReady(true)
|
||||
|
||||
const lspClient = new LanguageServerClient({ client, name: LspWorker.Kcl })
|
||||
return { lspClient }
|
||||
}, [
|
||||
setIsKclLspServerReady,
|
||||
// We need a token for authenticating the server.
|
||||
token,
|
||||
])
|
||||
@ -112,7 +132,7 @@ export const LspProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
// We do not want to restart the server, its just wasteful.
|
||||
const kclLSP = useMemo(() => {
|
||||
let plugin = null
|
||||
if (isKclLspServerReady && !TEST) {
|
||||
if (isKclLspServerReady && !TEST && kclLspClient) {
|
||||
// Set up the lsp plugin.
|
||||
const lsp = kclLanguage({
|
||||
documentUri: `file:///${DEFAULT_FILE_NAME}`,
|
||||
@ -127,10 +147,12 @@ export const LspProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
|
||||
// Re-execute the scene when the units change.
|
||||
useEffect(() => {
|
||||
let plugins = kclLspClient.plugins
|
||||
for (let plugin of plugins) {
|
||||
if (plugin.updateUnits && isStreamReady && isNetworkOkay) {
|
||||
plugin.updateUnits(defaultUnit.current)
|
||||
if (kclLspClient) {
|
||||
let plugins = kclLspClient.plugins
|
||||
for (let plugin of plugins) {
|
||||
if (plugin.updateUnits && isStreamReady && isNetworkOkay) {
|
||||
plugin.updateUnits(defaultUnit.current)
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [
|
||||
@ -145,19 +167,36 @@ export const LspProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
])
|
||||
|
||||
const { lspClient: copilotLspClient } = useMemo(() => {
|
||||
const intoServer: IntoServer = new IntoServer()
|
||||
const fromServer: FromServer = FromServer.create()
|
||||
const client = new Client(fromServer, intoServer)
|
||||
if (!TEST) {
|
||||
Server.initialize(intoServer, fromServer).then((lspServer) => {
|
||||
lspServer.start('copilot', token)
|
||||
setIsCopilotLspServerReady(true)
|
||||
})
|
||||
if (!token || token === '' || TEST) {
|
||||
return { lspClient: null }
|
||||
}
|
||||
|
||||
const lspClient = new LanguageServerClient({ client, name: 'copilot' })
|
||||
const lspWorker = new Worker({ name: 'copilot' })
|
||||
const initEvent: CopilotWorkerOptions = {
|
||||
token: token,
|
||||
devMode: DEV,
|
||||
}
|
||||
lspWorker.postMessage({
|
||||
worker: LspWorker.Copilot,
|
||||
eventType: LspWorkerEventType.Init,
|
||||
eventData: initEvent,
|
||||
})
|
||||
lspWorker.onmessage = function (e) {
|
||||
fromServer.add(e.data)
|
||||
}
|
||||
|
||||
const intoServer: IntoServer = new IntoServer(LspWorker.Copilot, lspWorker)
|
||||
const fromServer: FromServer = FromServer.create()
|
||||
const client = new Client(fromServer, intoServer)
|
||||
|
||||
setIsCopilotLspServerReady(true)
|
||||
|
||||
const lspClient = new LanguageServerClient({
|
||||
client,
|
||||
name: LspWorker.Copilot,
|
||||
})
|
||||
return { lspClient }
|
||||
}, [setIsCopilotLspServerReady, token])
|
||||
}, [token])
|
||||
|
||||
// Here we initialize the plugin which will start the client.
|
||||
// When we have multi-file support the name of the file will be a dep of
|
||||
@ -166,7 +205,7 @@ export const LspProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
// We do not want to restart the server, its just wasteful.
|
||||
const copilotLSP = useMemo(() => {
|
||||
let plugin = null
|
||||
if (isCopilotLspServerReady && !TEST) {
|
||||
if (isCopilotLspServerReady && !TEST && copilotLspClient) {
|
||||
// Set up the lsp plugin.
|
||||
const lsp = copilotPlugin({
|
||||
documentUri: `file:///${DEFAULT_FILE_NAME}`,
|
||||
@ -180,7 +219,13 @@ export const LspProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
return plugin
|
||||
}, [copilotLspClient, isCopilotLspServerReady])
|
||||
|
||||
const lspClients = [kclLspClient, copilotLspClient]
|
||||
let lspClients: LanguageServerClient[] = []
|
||||
if (kclLspClient) {
|
||||
lspClients.push(kclLspClient)
|
||||
}
|
||||
if (copilotLspClient) {
|
||||
lspClients.push(copilotLspClient)
|
||||
}
|
||||
|
||||
const onProjectClose = (
|
||||
file: FileEntry | null,
|
||||
|
Reference in New Issue
Block a user