refactor(server): use TSS_DEBUG & TSS_DEBUG_BRK for debug port

This commit is contained in:
Qiming Zhao 2021-12-22 14:24:04 +08:00
parent f0820d2357
commit 65e1f75be5
6 changed files with 82 additions and 56 deletions

View file

@ -116,7 +116,6 @@ for guide of coc.nvim's configuration.
- `tsserver.log`:Log level of tsserver, default: `"off"`
- `tsserver.trace.server`:Trace level of tsserver, default: `"off"`
- `tsserver.pluginPaths`:Folders contains tsserver plugins, default: `[]`
- `tsserver.debugPort`:Debug port number of tsserver
- `tsserver.watchOptions`:Configure which watching strategies should be used to
keep track of files and directories. Requires using TypeScript 3.8+ in the
workspace, default: `undefined`

View file

@ -238,10 +238,6 @@
},
"description": "Folders contains tsserver plugins"
},
"tsserver.debugPort": {
"type": "number",
"description": "Debug port number of tsserver"
},
"tsserver.reportStyleChecksAsWarnings": {
"type": "boolean",
"default": true

View file

@ -25,22 +25,22 @@ import Tracer from './utils/tracer'
import { inferredProjectConfig } from './utils/tsconfig'
import { TypeScriptVersion, TypeScriptVersionProvider } from './utils/versionProvider'
import VersionStatus from './utils/versionStatus'
import { ICallback, Reader } from './utils/wireProtocol'
import { Reader } from './utils/wireProtocol'
interface ToCancelOnResourceChanged {
readonly resource: string
cancel(): void
}
class ForkedTsServerProcess {
constructor(private childProcess: cp.ChildProcess) {}
class ForkedTsServerProcess implements Disposable {
private readonly _reader: Reader<Proto.Response>
constructor(private childProcess: cp.ChildProcess) {
this._reader = new Reader<Proto.Response>(this.childProcess.stdout)
}
public readonly toCancelOnResourceChange = new Set<ToCancelOnResourceChanged>()
public onError(cb: (err: Error) => void): void {
this.childProcess.on('error', cb)
}
public onExit(cb: (err: any) => void): void {
this.childProcess.on('exit', cb)
}
@ -52,16 +52,22 @@ class ForkedTsServerProcess {
)
}
public createReader(
callback: ICallback<Proto.Response>,
onError: (error: any) => void
): void {
// tslint:disable-next-line:no-unused-expression
new Reader<Proto.Response>(this.childProcess.stdout, callback, onError)
public onData(handler: (data: Proto.Response) => void): void {
this._reader.onData(handler)
}
public onError(handler: (err: Error) => void): void {
this.childProcess.on('error', handler)
this._reader.onError(handler)
}
public kill(): void {
this.childProcess.kill()
this._reader.dispose()
}
public dispose(): void {
this._reader.dispose()
}
}
@ -296,19 +302,26 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
this.versionStatus.onDidChangeTypeScriptVersion(currentVersion)
this.lastError = null
const tsServerForkArgs = await this.getTsServerArgs(currentVersion)
const debugPort = this._configuration.debugPort
const maxTsServerMemory = this._configuration.maxTsServerMemory
const options = {
execArgv: [
...(debugPort ? [`--inspect=${debugPort}`] : []), // [`--debug-brk=5859`]
...(maxTsServerMemory ? [`--max-old-space-size=${maxTsServerMemory}`] : []),
],
cwd: workspace.root
}
const options = { execArgv: this.getExecArgv() }
this.servicePromise = this.startProcess(currentVersion, tsServerForkArgs, options, resendModels)
return this.servicePromise
}
private getExecArgv(): string[] {
const args: string[] = []
const debugPort = getDebugPort()
if (debugPort) {
const isBreak = process.env[process.env.remoteName ? 'TSS_REMOTE_DEBUG_BRK' : 'TSS_DEBUG_BRK'] !== undefined
const inspectFlag = isBreak ? '--inspect-brk' : '--inspect'
args.push(`${inspectFlag}=${debugPort}`)
}
const maxTsServerMemory = this._configuration.maxTsServerMemory
if (maxTsServerMemory) {
args.push(`--max-old-space-size=${maxTsServerMemory}`)
}
return args
}
private startProcess(currentVersion: TypeScriptVersion, args: string[], options: IForkOptions, resendModels: boolean): Promise<ForkedTsServerProcess> {
this.state = ServiceStat.Starting
return new Promise((resolve, reject) => {
@ -347,16 +360,11 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
this.info(`TSServer log file: ${this.tsServerLogFile || ''}`)
this.serviceExited(!this.isRestarting)
this.isRestarting = false
handle.dispose()
})
handle.onData(msg => {
this.dispatchMessage(msg)
})
handle.createReader(
msg => {
this.dispatchMessage(msg)
},
error => {
this.error('ReaderError', error)
}
)
resolve(handle)
this.serviceStarted(resendModels)
this._onTsServerStarted.fire(currentVersion.version)
@ -1013,3 +1021,15 @@ function getQueueingType(
}
return lowPriority ? RequestQueueingType.LowPriority : RequestQueueingType.Normal
}
function getDebugPort(): number | undefined {
let debugBrk = process.env[process.env.remoteName ? 'TSS_REMOTE_DEBUG_BRK' : 'TSS_DEBUG_BRK']
let value = debugBrk || process.env[process.env.remoteName ? 'TSS_REMOTE_DEBUG_BRK' : 'TSS_DEBUG_BRK']
if (value) {
const port = parseInt(value)
if (!isNaN(port)) {
return port
}
}
return undefined
}

View file

@ -108,10 +108,6 @@ export class TypeScriptServiceConfiguration {
return this._configuration.get<number>('maxTsServerMemory', 0)
}
public get debugPort(): number | null {
return this._configuration.get<number>('debugPort', parseInt(process.env['TSS_DEBUG'], 10))
}
public get npmLocation(): string | null {
let path = this._configuration.get<string>('npm', '')
if (path) return workspace.expand(path)

View file

@ -98,16 +98,12 @@ export function fork(
): void {
let callbackCalled = false
const resolve = (result: cp.ChildProcess) => {
if (callbackCalled) {
return
}
if (callbackCalled) return
callbackCalled = true
callback(null, result)
}
const reject = (err: any) => {
if (callbackCalled) {
return
}
if (callbackCalled) return
callbackCalled = true
callback(err, null)
}
@ -123,7 +119,7 @@ export function fork(
stdOutPipeName,
stdErrPipeName
)
newEnv['NODE_PATH'] = path.join(modulePath, '..', '..', '..') // tslint:disable-line
newEnv['NODE_PATH'] = path.join(modulePath, '..', '..', '..')
let childProcess: cp.ChildProcess
// Begin listening to stderr pipe
@ -165,6 +161,7 @@ export function fork(
const bootstrapperPath = path.resolve(__dirname, '../bin/tsserverForkStart')
childProcess = cp.fork(bootstrapperPath, [modulePath].concat(args), {
silent: true,
cwd: undefined,
env: newEnv,
execArgv: options.execArgv
})

View file

@ -2,7 +2,9 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { disposeAll } from 'coc.nvim'
import stream from 'stream'
import { Disposable, Emitter } from 'vscode-languageserver-protocol'
const DefaultSize = 8192
const ContentLength = 'Content-Length: '
@ -99,18 +101,30 @@ export interface ICallback<T> {
(data: T): void // tslint:disable-line
}
export class Reader<T> {
export class Reader<T> implements Disposable {
private readonly buffer: ProtocolBuffer = new ProtocolBuffer()
private nextMessageLength = -1
private disposables: Disposable[] = []
public constructor(
private readonly readable: stream.Readable,
private readonly callback: ICallback<T>,
private readonly onError: (error: any) => void
) {
this.readable.on('data', (data: Buffer) => {
private readonly _onError = new Emitter<Error>()
public readonly onError = this._onError.event
private readonly _onData = new Emitter<T>()
public readonly onData = this._onData.event
public constructor(readable: stream.Readable) {
const onData = (data: Buffer) => {
this.onLengthData(data)
}
readable.on('data', onData)
this.disposables.push({
dispose: () => {
readable.off('data', onData)
}
})
this.disposables.push(this._onError)
this.disposables.push(this._onData)
}
private onLengthData(data: Buffer): void {
@ -129,10 +143,14 @@ export class Reader<T> {
}
this.nextMessageLength = -1
const json = JSON.parse(msg)
this.callback(json)
this._onData.fire(json)
}
} catch (e) {
this.onError(e)
this._onError.fire(e)
}
}
public dispose(): void {
disposeAll(this.disposables)
}
}