parent
4bc14d7ce2
commit
156fe981c7
4 changed files with 139 additions and 128 deletions
|
@ -1,126 +0,0 @@
|
|||
import { commands, Disposable, disposeAll, StatusBarItem, TaskOptions, Uri, window, workspace } from 'coc.nvim'
|
||||
import path from 'path'
|
||||
import TypeScriptServiceClient from '../typescriptServiceClient'
|
||||
|
||||
const countRegex = /Found\s+(\d+)\s+error/
|
||||
const errorRegex = /^(.+)\((\d+),(\d+)\):\s(\w+)\sTS(\d+):\s*(.+)$/
|
||||
|
||||
export default class WatchProject implements Disposable {
|
||||
private disposables: Disposable[] = []
|
||||
public static readonly id: string = 'tsserver.watchBuild'
|
||||
public static readonly startTexts: string[] = ['Starting compilation in watch mode', 'Starting incremental compilation']
|
||||
private statusItem: StatusBarItem
|
||||
private task: any
|
||||
private options: TaskOptions
|
||||
|
||||
public constructor(
|
||||
private client: TypeScriptServiceClient
|
||||
) {
|
||||
this.statusItem = window.createStatusBarItem(1, { progress: true })
|
||||
let task = this.task = workspace.createTask('TSC')
|
||||
|
||||
this.disposables.push(commands.registerCommand(WatchProject.id, async () => {
|
||||
let opts = this.options = await this.getOptions()
|
||||
await this.start(opts)
|
||||
}))
|
||||
task.onExit(code => {
|
||||
if (code != 0) {
|
||||
window.showMessage(`TSC exit with code ${code}`, 'warning')
|
||||
}
|
||||
this.onStop()
|
||||
})
|
||||
task.onStdout(lines => {
|
||||
for (let line of lines) {
|
||||
this.onLine(line)
|
||||
}
|
||||
})
|
||||
task.onStderr(lines => {
|
||||
window.showMessage(`TSC error: ` + lines.join('\n'), 'error')
|
||||
})
|
||||
this.disposables.push(Disposable.create(() => {
|
||||
task.dispose()
|
||||
}))
|
||||
this.check().catch(_e => {
|
||||
// noop
|
||||
})
|
||||
}
|
||||
|
||||
private async check(): Promise<void> {
|
||||
let running = await this.task.running
|
||||
if (running) {
|
||||
this.options = await this.getOptions()
|
||||
this.statusItem.isProgress = false
|
||||
this.statusItem.text = '?'
|
||||
this.statusItem.show()
|
||||
} else {
|
||||
this.onStop()
|
||||
}
|
||||
}
|
||||
|
||||
private async start(options: TaskOptions): Promise<void> {
|
||||
await this.task.start(options)
|
||||
}
|
||||
|
||||
private onStop(): void {
|
||||
this.statusItem.hide()
|
||||
}
|
||||
|
||||
private onStart(): void {
|
||||
this.statusItem.text = 'compiling'
|
||||
this.statusItem.isProgress = true
|
||||
this.statusItem.show()
|
||||
workspace.nvim.call('setqflist', [[]], true)
|
||||
}
|
||||
|
||||
private onLine(line: string): void {
|
||||
if (countRegex.test(line)) {
|
||||
let ms = line.match(countRegex)
|
||||
this.statusItem.text = ms[1] == '0' ? '✓' : '✗'
|
||||
this.statusItem.isProgress = false
|
||||
} else if (WatchProject.startTexts.findIndex(s => line.indexOf(s) !== -1) != -1) {
|
||||
this.onStart()
|
||||
} else {
|
||||
let ms = line.match(errorRegex)
|
||||
if (!ms) return
|
||||
let fullpath = path.join(this.options.cwd, ms[1])
|
||||
let uri = Uri.file(fullpath).toString()
|
||||
let doc = workspace.getDocument(uri)
|
||||
let bufnr = doc ? doc.bufnr : null
|
||||
let item = {
|
||||
filename: fullpath,
|
||||
lnum: Number(ms[2]),
|
||||
col: Number(ms[3]),
|
||||
text: `[tsc ${ms[5]}] ${ms[6]}`,
|
||||
type: /error/i.test(ms[4]) ? 'E' : 'W'
|
||||
} as any
|
||||
if (bufnr) item.bufnr = bufnr
|
||||
workspace.nvim.call('setqflist', [[item], 'a'])
|
||||
}
|
||||
}
|
||||
|
||||
public async getOptions(): Promise<TaskOptions> {
|
||||
let { tscPath } = this.client
|
||||
if (!tscPath) {
|
||||
window.showMessage(`Local & global tsc not found`, 'error')
|
||||
return
|
||||
}
|
||||
|
||||
const tsconfigPath = workspace.getConfiguration('tsserver').get<string>('tsconfigPath', 'tsconfig.json')
|
||||
let find = await workspace.findUp([tsconfigPath])
|
||||
if (!find) {
|
||||
window.showMessage(`${tsconfigPath} not found!`, 'error')
|
||||
return
|
||||
}
|
||||
|
||||
let root = path.dirname(find)
|
||||
return {
|
||||
cmd: tscPath,
|
||||
args: ['-p', tsconfigPath, '--watch', 'true', '--pretty', 'false'],
|
||||
cwd: root
|
||||
}
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
disposeAll(this.disposables)
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ import { Disposable, DocumentSelector, Emitter, Event } from 'vscode-languageser
|
|||
import { PluginManager } from '../utils/plugins'
|
||||
import { AutoFixCommand, Command, ConfigurePluginCommand, FileReferencesCommand, OpenTsServerLogCommand, ReloadProjectsCommand, SourceDefinitionCommand, TypeScriptGoToProjectConfigCommand } from './commands'
|
||||
import { OrganizeImportsCommand, SourceImportsCommand } from './organizeImports'
|
||||
import WatchProject from './watchBuild'
|
||||
import TypeScriptServiceClientHost from './typescriptServiceClientHost'
|
||||
import { LanguageDescription, standardLanguageDescriptions } from './utils/languageDescription'
|
||||
|
||||
|
@ -43,6 +44,7 @@ export default class TsserverService implements IServiceProvider {
|
|||
this.selector = this.descriptions.reduce((arr, c) => {
|
||||
return arr.concat(c.languageIds)
|
||||
}, [])
|
||||
console.log(111)
|
||||
this.registCommands()
|
||||
}
|
||||
|
||||
|
@ -61,6 +63,14 @@ export default class TsserverService implements IServiceProvider {
|
|||
let { id, execute } = cmd
|
||||
subscriptions.push(commands.registerCommand(id as string, execute, cmd))
|
||||
}
|
||||
let watchProject = new WatchProject(this)
|
||||
subscriptions.push(watchProject)
|
||||
registCommand({
|
||||
id: WatchProject.id,
|
||||
execute: () => {
|
||||
return watchProject.execute()
|
||||
}
|
||||
})
|
||||
registCommand(new ConfigurePluginCommand(this.pluginManager))
|
||||
registCommand(new AutoFixCommand(this))
|
||||
registCommand(new ReloadProjectsCommand(this))
|
||||
|
|
|
@ -8,7 +8,6 @@ import { flatten } from '../utils/arrays'
|
|||
import { PluginManager } from '../utils/plugins'
|
||||
import { DiagnosticKind } from './features/diagnostics'
|
||||
import FileConfigurationManager from './features/fileConfigurationManager'
|
||||
import WatchBuild from './features/watchBuild'
|
||||
import WorkspaceSymbolProvider from './features/workspaceSymbols'
|
||||
import LanguageProvider from './languageProvider'
|
||||
import * as Proto from './protocol'
|
||||
|
@ -66,7 +65,6 @@ export default class TypeScriptServiceClientHost implements Disposable {
|
|||
}, null, this.disposables)
|
||||
|
||||
// features
|
||||
this.disposables.push(new WatchBuild(this.client))
|
||||
this.disposables.push(languages.registerWorkspaceSymbolProvider(new WorkspaceSymbolProvider(this.client, allModeIds)))
|
||||
this.client.onConfigDiagnosticsReceived(diag => {
|
||||
let { body } = diag
|
||||
|
|
129
src/server/watchBuild.ts
Normal file
129
src/server/watchBuild.ts
Normal file
|
@ -0,0 +1,129 @@
|
|||
import { Disposable, disposeAll, StatusBarItem, TaskOptions, Uri, window, workspace } from 'coc.nvim'
|
||||
import path from 'path'
|
||||
import type TsserverService from '../server'
|
||||
|
||||
const countRegex = /Found\s+(\d+)\s+error/
|
||||
const errorRegex = /^(.+)\((\d+),(\d+)\):\s(\w+)\sTS(\d+):\s*(.+)$/
|
||||
|
||||
export default class WatchProject implements Disposable {
|
||||
private disposables: Disposable[] = []
|
||||
public static readonly id: string = 'tsserver.watchBuild'
|
||||
public static readonly startTexts: string[] = ['Starting compilation in watch mode', 'Starting incremental compilation']
|
||||
private statusItem: StatusBarItem
|
||||
private task: any
|
||||
private options: TaskOptions
|
||||
|
||||
public constructor(
|
||||
private readonly service: TsserverService
|
||||
) {
|
||||
this.statusItem = window.createStatusBarItem(1, { progress: true })
|
||||
this.disposables.push(this.statusItem)
|
||||
let task = this.task = workspace.createTask('TSC')
|
||||
|
||||
task.onExit(code => {
|
||||
if (code != 0) {
|
||||
window.showMessage(`TSC exit with code ${code}`, 'warning')
|
||||
}
|
||||
this.onStop()
|
||||
})
|
||||
task.onStdout(lines => {
|
||||
for (let line of lines) {
|
||||
this.onLine(line)
|
||||
}
|
||||
})
|
||||
task.onStderr(lines => {
|
||||
window.showMessage(`TSC error: ` + lines.join('\n'), 'error')
|
||||
})
|
||||
this.disposables.push(Disposable.create(() => {
|
||||
task.dispose()
|
||||
}))
|
||||
this.check().catch(_e => {
|
||||
// noop
|
||||
})
|
||||
}
|
||||
|
||||
public async execute(): Promise<void> {
|
||||
let opts = this.options = await this.getOptions()
|
||||
await this.start(opts)
|
||||
}
|
||||
|
||||
private async check(): Promise<void> {
|
||||
let running = await this.task.running
|
||||
if (running) {
|
||||
this.options = await this.getOptions()
|
||||
this.statusItem.isProgress = false
|
||||
this.statusItem.text = '?'
|
||||
this.statusItem.show()
|
||||
} else {
|
||||
this.onStop()
|
||||
}
|
||||
}
|
||||
|
||||
private async start(options: TaskOptions): Promise<void> {
|
||||
await this.task.start(options)
|
||||
}
|
||||
|
||||
private onStop(): void {
|
||||
this.statusItem.hide()
|
||||
}
|
||||
|
||||
private onStart(): void {
|
||||
this.statusItem.text = 'compiling'
|
||||
this.statusItem.isProgress = true
|
||||
this.statusItem.show()
|
||||
workspace.nvim.call('setqflist', [[]], true)
|
||||
}
|
||||
|
||||
private onLine(line: string): void {
|
||||
if (countRegex.test(line)) {
|
||||
let ms = line.match(countRegex)
|
||||
this.statusItem.text = ms[1] == '0' ? '✓' : '✗'
|
||||
this.statusItem.isProgress = false
|
||||
} else if (WatchProject.startTexts.findIndex(s => line.indexOf(s) !== -1) != -1) {
|
||||
this.onStart()
|
||||
} else {
|
||||
let ms = line.match(errorRegex)
|
||||
if (!ms) return
|
||||
let fullpath = path.join(this.options.cwd, ms[1])
|
||||
let uri = Uri.file(fullpath).toString()
|
||||
let doc = workspace.getDocument(uri)
|
||||
let bufnr = doc ? doc.bufnr : null
|
||||
let item = {
|
||||
filename: fullpath,
|
||||
lnum: Number(ms[2]),
|
||||
col: Number(ms[3]),
|
||||
text: `[tsc ${ms[5]}] ${ms[6]}`,
|
||||
type: /error/i.test(ms[4]) ? 'E' : 'W'
|
||||
} as any
|
||||
if (bufnr) item.bufnr = bufnr
|
||||
workspace.nvim.call('setqflist', [[item], 'a'])
|
||||
}
|
||||
}
|
||||
|
||||
public async getOptions(): Promise<TaskOptions> {
|
||||
let client = await this.service.getClientHost()
|
||||
let { tscPath } = client.serviceClient
|
||||
if (!tscPath) {
|
||||
window.showMessage(`Local & global tsc not found`, 'error')
|
||||
return
|
||||
}
|
||||
|
||||
const tsconfigPath = workspace.getConfiguration('tsserver').get<string>('tsconfigPath', 'tsconfig.json')
|
||||
let find = await workspace.findUp([tsconfigPath])
|
||||
if (!find) {
|
||||
window.showMessage(`${tsconfigPath} not found!`, 'error')
|
||||
return
|
||||
}
|
||||
|
||||
let root = path.dirname(find)
|
||||
return {
|
||||
cmd: tscPath,
|
||||
args: ['-p', tsconfigPath, '--watch', 'true', '--pretty', 'false'],
|
||||
cwd: root
|
||||
}
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
disposeAll(this.disposables)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue