fix api with IServiceProvider

Support for watch tsserver.enable configuration
This commit is contained in:
Qiming Zhao 2022-02-16 20:38:19 +08:00
parent 78da8a3514
commit 6cdbf56da5
No known key found for this signature in database
GPG key ID: 9722CD0E8D4DCB8C
5 changed files with 94 additions and 55 deletions

View file

@ -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.

View file

@ -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<API> {
let { subscriptions, logger } = context
const config = workspace.getConfiguration().get<any>('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 => {

View file

@ -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<void>()
public readonly onServiceReady: Event<void> = 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<boolean>('enableJavascript')
const enableJavascript = config.get<boolean>('enableJavascript', true)
this.enable = config.get<boolean>('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<boolean>('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<void> {
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<void> {
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)
}
}

View file

@ -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<Proto.Response>()
this._requestQueue = new RequestQueue()
this._pendingResponses = new Set<number>()
if (this.noRestart) {
this.noRestart = false
return
}
if (restart) {
const diff = Date.now() - this.lastStart
this.numberRestarts++

View file

@ -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
}