From 6cdbf56da529604da3221bb6fa30de3550505d02 Mon Sep 17 00:00:00 2001 From: Qiming Zhao Date: Wed, 16 Feb 2022 20:38:19 +0800 Subject: [PATCH] fix api with IServiceProvider Support for watch tsserver.enable configuration --- history.md | 9 +++ src/index.ts | 35 +-------- src/server/index.ts | 95 ++++++++++++++++++----- src/server/typescriptServiceClient.ts | 6 ++ src/server/typescriptServiceClientHost.ts | 4 - 5 files changed, 94 insertions(+), 55 deletions(-) diff --git a/history.md b/history.md index 9bd595d..37bded5 100644 --- a/history.md +++ b/history.md @@ -1,3 +1,12 @@ +# 1.9.10 + +- Watch for `tsserver.enable` configuration to change service state. +- Fix tsserver not work well with `:CocList services` + +# 1.9.9 + +- Use documentChanges for workspaceEdit. + # 1.9.8 - Log to output when document content exceed limit of semantic tokens. diff --git a/src/index.ts b/src/index.ts index 28b7c42..113d965 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,5 @@ -import { commands, ExtensionContext, services, workspace } from 'coc.nvim' +import { ExtensionContext, services } from 'coc.nvim' import TsserverService from './server' -import { AutoFixCommand, Command, ConfigurePluginCommand, FileReferencesCommand, OpenTsServerLogCommand, ReloadProjectsCommand, TypeScriptGoToProjectConfigCommand } from './server/commands' -import { OrganizeImportsCommand, SourceImportsCommand } from './server/organizeImports' import { PluginManager } from './utils/plugins' interface API { @@ -9,35 +7,10 @@ interface API { } export async function activate(context: ExtensionContext): Promise { - let { subscriptions, logger } = context - const config = workspace.getConfiguration().get('tsserver', {}) - if (!config.enable) return + let { subscriptions } = context const pluginManager = new PluginManager() - const service = new TsserverService(pluginManager) - function registCommand(cmd: Command): void { - let { id, execute } = cmd - subscriptions.push(commands.registerCommand(id as string, execute, cmd)) - } - registCommand(new ConfigurePluginCommand(pluginManager)) - registCommand(new AutoFixCommand(service)) - registCommand(new ReloadProjectsCommand(service)) - registCommand(new FileReferencesCommand(service)) - registCommand(new OpenTsServerLogCommand(service)) - registCommand(new TypeScriptGoToProjectConfigCommand(service)) - registCommand(new OrganizeImportsCommand(service)) - registCommand(new SourceImportsCommand(service)) - registCommand({ - id: 'tsserver.restart', - execute: (): void => { - service.restart() - } - }) - - service.start().then(() => { - subscriptions.push(services.regist(service)) - }, e => { - logger.error(`Error on service start:`, e) - }) + const service = new TsserverService(pluginManager, context.subscriptions) + subscriptions.push(services.regist(service)) return { configurePlugin: (pluginId: string, configuration: {}): void => { diff --git a/src/server/index.ts b/src/server/index.ts index 3637093..ce7698e 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -1,6 +1,8 @@ -import { disposeAll, IServiceProvider, ServiceStat, workspace, WorkspaceConfiguration } from 'coc.nvim' +import { commands, disposeAll, IServiceProvider, ServiceStat, workspace, WorkspaceConfiguration } from 'coc.nvim' import { Disposable, DocumentSelector, Emitter, Event } from 'vscode-languageserver-protocol' import { PluginManager } from '../utils/plugins' +import { AutoFixCommand, Command, ConfigurePluginCommand, FileReferencesCommand, OpenTsServerLogCommand, ReloadProjectsCommand, TypeScriptGoToProjectConfigCommand } from './commands' +import { OrganizeImportsCommand, SourceImportsCommand } from './organizeImports' import TypeScriptServiceClientHost from './typescriptServiceClientHost' import { LanguageDescription, standardLanguageDescriptions } from './utils/languageDescription' @@ -10,23 +12,69 @@ export default class TsserverService implements IServiceProvider { public enable: boolean // supported language types public selector: DocumentSelector - public state = ServiceStat.Initial + public _state = ServiceStat.Initial public clientHost: TypeScriptServiceClientHost private _onDidServiceReady = new Emitter() public readonly onServiceReady: Event = this._onDidServiceReady.event private readonly disposables: Disposable[] = [] private descriptions: LanguageDescription[] = [] - constructor(private pluginManager: PluginManager) { + constructor(private pluginManager: PluginManager, private readonly subscriptions: Disposable[]) { const config = workspace.getConfiguration('tsserver') - const enableJavascript = !!config.get('enableJavascript') + const enableJavascript = config.get('enableJavascript', true) this.enable = config.get('enable') this.descriptions = standardLanguageDescriptions.filter(o => { return enableJavascript ? true : o.id != 'javascript' }) + workspace.onDidChangeConfiguration(e => { + if (e.affectsConfiguration('tsserver')) { + const config = workspace.getConfiguration('tsserver') + let enable = this.enable + this.enable = config.get('enable', true) + if (enable !== this.enable) { + if (this.enable) { + void this.start() + } else { + void this.stop() + } + } + } + }) this.selector = this.descriptions.reduce((arr, c) => { return arr.concat(c.modeIds) }, []) + this.registCommands() + } + + // public state = ServiceStat.Initial + + public get state(): ServiceStat { + if (this.clientHost) { + return this.clientHost.serviceClient.state + } + return this._state + } + + private registCommands(): void { + let { subscriptions } = this + const registCommand = (cmd: Command): void => { + let { id, execute } = cmd + subscriptions.push(commands.registerCommand(id as string, execute, cmd)) + } + registCommand(new ConfigurePluginCommand(this.pluginManager)) + registCommand(new AutoFixCommand(this)) + registCommand(new ReloadProjectsCommand(this)) + registCommand(new FileReferencesCommand(this)) + registCommand(new OpenTsServerLogCommand(this)) + registCommand(new TypeScriptGoToProjectConfigCommand(this)) + registCommand(new OrganizeImportsCommand(this)) + registCommand(new SourceImportsCommand(this)) + registCommand({ + id: 'tsserver.restart', + execute: (): void => { + this.restart() + } + }) } public get config(): WorkspaceConfiguration { @@ -52,38 +100,45 @@ export default class TsserverService implements IServiceProvider { } public start(): Promise { - if (this.clientHost) return - this.state = ServiceStat.Starting + if (!this.enable) return + if (this.clientHost) { + let client = this.clientHost.serviceClient + client.restartTsServer() + return + } + this._state = ServiceStat.Starting this.clientHost = new TypeScriptServiceClientHost(this.descriptions, this.pluginManager) - this.disposables.push(this.clientHost) let client = this.clientHost.serviceClient return new Promise(resolve => { client.onReady(() => { - Object.defineProperty(this, 'state', { - get: () => { - return this.clientHost.serviceClient.state - } - }) this._onDidServiceReady.fire(void 0) resolve() }) }) } - public dispose(): void { - disposeAll(this.disposables) - } - public restart(): void { - if (!this.clientHost) return - let client = this.clientHost.serviceClient - client.restartTsServer() + if (!this.enable) return + if (this.clientHost) { + let client = this.clientHost.serviceClient + client.restartTsServer() + } else { + void this.start() + } } public async stop(): Promise { if (!this.clientHost) return - this.clientHost.reset() let client = this.clientHost.serviceClient await client.stop() + this.clientHost.dispose() + this.clientHost = null + this._state = ServiceStat.Stopped + } + + public dispose(): void { + void this.stop() + this._onDidServiceReady.dispose() + disposeAll(this.disposables) } } diff --git a/src/server/typescriptServiceClient.ts b/src/server/typescriptServiceClient.ts index 46cd5cf..4e6dc7d 100644 --- a/src/server/typescriptServiceClient.ts +++ b/src/server/typescriptServiceClient.ts @@ -34,6 +34,7 @@ export interface TsDiagnostics { export default class TypeScriptServiceClient implements ITypeScriptServiceClient { private token: number = 0 + private noRestart = false public state = ServiceStat.Initial public readonly logger: Logger = new Logger() public readonly bufferSyncSupport: BufferSyncSupport @@ -169,6 +170,7 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient tsServerProcess.onExit(() => { resolve() }) + this.noRestart = true tsServerProcess.kill() } else { resolve() @@ -381,6 +383,10 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient this._callbacks = new CallbackMap() this._requestQueue = new RequestQueue() this._pendingResponses = new Set() + if (this.noRestart) { + this.noRestart = false + return + } if (restart) { const diff = Date.now() - this.lastStart this.numberRestarts++ diff --git a/src/server/typescriptServiceClientHost.ts b/src/server/typescriptServiceClientHost.ts index 9b04e72..277efb5 100644 --- a/src/server/typescriptServiceClientHost.ts +++ b/src/server/typescriptServiceClientHost.ts @@ -160,10 +160,6 @@ export default class TypeScriptServiceClientHost implements Disposable { this.ataProgressReporter.dispose() } - public reset(): void { - this.fileConfigurationManager.reset() - } - public get serviceClient(): TypeScriptServiceClient { return this.client }