new features as VSCode

* Support tsserver.watchOptions
* Improve triggerCharacters for completion
* Configure command on server startup
This commit is contained in:
Qiming Zhao 2020-04-17 18:58:07 +08:00
parent 9c54e2dee7
commit fe05e038d5
8 changed files with 97 additions and 22 deletions

View file

@ -103,6 +103,7 @@ Checkout [using the configuration file](https://github.com/neoclide/coc.nvim/wik
- `tsserver.trace.server`:Trace level of tsserver, default: `"off"`
- `tsserver.pluginRoot`:Folder 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.
- `tsserver.reportStyleChecksAsWarnings` default: `true`
- `tsserver.implicitProjectConfig.checkJs`:Enable checkJs for implicit project, default: `false`
- `tsserver.implicitProjectConfig.experimentalDecorators`:Enable experimentalDecorators for implicit project, default: `false`

View file

@ -139,6 +139,47 @@
"default": 0,
"description": "Set the maximum amount of memory to allocate to the TypeScript server process"
},
"tsserver.watchOptions": {
"type": "object",
"description": "Configure which watching strategies should be used to keep track of files and directories. Requires using TypeScript 3.8+ in the workspace.",
"properties": {
"watchFile": {
"type": "string",
"description": "Strategy for how individual files are watched.",
"enum": [
"fixedPollingInterval",
"priorityPollingInterval",
"dynamicPriorityPolling",
"useFsEvents",
"useFsEventsOnParentDirectory"
],
"default": "useFsEvents"
},
"watchDirectory": {
"type": "string",
"description": "Strategy for how entire directory trees are watched under systems that lack recursive file-watching functionality.",
"enum": [
"fixedPollingInterval",
"dynamicPriorityPolling",
"useFsEvents"
],
"default": "useFsEvents"
},
"fallbackPolling": {
"type": "string",
"description": "When using file system events, this option specifies the polling strategy that gets used when the system runs out of native file watchers and/or doesnt support native file watchers.",
"enum": [
"fixedPollingInterval",
"priorityPollingInterval",
"dynamicPriorityPolling"
]
},
"synchronousWatchDirectory": {
"type": "boolean",
"description": "Disable deferred watching on directories. Deferred watching is useful when lots of file changes might occur at once (e.g. a change in node_modules from running npm install), but you might want to disable it with this flag for some less-common setups."
}
}
},
"tsserver.tsdk": {
"type": "string",
"default": "",

View file

@ -120,6 +120,11 @@ class BufferSynchronizer {
f(this._pending)
}
}
public reset(): void {
this._pending = {}
this._pendingFiles.clear()
}
}
export default class BufferSyncSupport {
@ -179,7 +184,7 @@ export default class BufferSyncSupport {
disposeAll(this.disposables)
}
private onDidOpenTextDocument(document: TextDocument): void {
public onDidOpenTextDocument(document: TextDocument): void {
if (!this.modeIds.has(document.languageId)) return
let { uri } = document
let filepath = this.client.toPath(uri)
@ -339,6 +344,15 @@ export default class BufferSyncSupport {
}
return this._validateTypeScript
}
public reinitialize(): void {
this.pendingDiagnostics.clear()
this.pendingGetErr?.cancel()
this.synchronizer.reset()
for (let doc of workspace.documents) {
this.onDidOpenTextDocument(doc.textDocument)
}
}
}
class GetErrRequest {

View file

@ -51,7 +51,7 @@ class ApplyCompletionCodeActionCommand implements CommandItem {
export default class TypeScriptCompletionItemProvider implements CompletionItemProvider {
public static readonly triggerCharacters = ['.', '"', '\'', '/', '@']
public static readonly triggerCharacters = ['.', '"', '\'', '`', '/', '@', '<', '#']
private completeOption: SuggestOptions
constructor(
@ -185,14 +185,23 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP
}
private getTsTriggerCharacter(context: CompletionContext): Proto.CompletionsTriggerCharacter | undefined {
// Workaround for https://github.com/Microsoft/TypeScript/issues/27321
if (context.triggerCharacter === '@'
&& this.client.apiVersion.gte(API.v310) && this.client.apiVersion.lt(API.v320)
) {
return undefined
}
// return context.triggerCharacter as Proto.CompletionsTriggerCharacter
switch (context.triggerCharacter) {
case '@': // Workaround for https://github.com/Microsoft/TypeScript/issues/27321
return this.client.apiVersion.gte(API.v310) && this.client.apiVersion.lt(API.v320) ? undefined : '@'
return context.triggerCharacter as Proto.CompletionsTriggerCharacter
case '#': // Workaround for https://github.com/microsoft/TypeScript/issues/36367
return this.client.apiVersion.lt(API.v381) ? undefined : '#'
case '.':
case '"':
case '\'':
case '`':
case '/':
case '<':
return context.triggerCharacter
}
return undefined
}
/**

View file

@ -59,15 +59,14 @@ export default class FileConfigurationManager {
this.cachedMap.set(document.uri, currentOptions)
const args: Proto.ConfigureRequestArguments = {
file,
hostInfo: `nvim-coc ${workspace.version}`,
...currentOptions
}
await this.client.execute('configure', args, CancellationToken.None)
}
public async ensureConfigurationForDocument(document: TextDocument): Promise<void> {
let opts = await workspace.getFormatOptions(document.uri)
if (!this.client.bufferSyncSupport.has(document.uri)) return
let opts = await workspace.getFormatOptions(document.uri)
return this.ensureConfigurationOptions(document, opts.insertSpaces, opts.tabSize)
}

View file

@ -68,8 +68,6 @@ export default class TsserverService implements IServiceProvider {
private async ensureConfiguration(): Promise<void> {
if (!this.clientHost) return
let document = await workspace.document
await wait(100)
let uri = Uri.parse(document.uri)
let language = this.clientHost.findLanguage(uri)
if (!language) return

View file

@ -16,7 +16,6 @@ import API from './utils/api'
import { TsServerLogLevel, TypeScriptServiceConfiguration } from './utils/configuration'
import Logger from './utils/logger'
import { fork, getTempFile, getTempDirectory, IForkOptions, makeRandomHexString } from './utils/process'
import { languageIds } from './utils/languageModeIds'
import Tracer from './utils/tracer'
import { inferredProjectConfig } from './utils/tsconfig'
import { TypeScriptVersion, TypeScriptVersionProvider } from './utils/versionProvider'
@ -385,18 +384,27 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
}
private serviceStarted(resendModels: boolean): void {
let document = workspace.getDocument(workspace.bufnr)
if (document && languageIds.indexOf(document.filetype) !== -1) {
this.fileConfigurationManager.ensureConfigurationForDocument(document.textDocument) // tslint:disable-line
} else {
const configureOptions: Proto.ConfigureRequestArguments = {
hostInfo: 'nvim-coc'
}
this.execute('configure', configureOptions, CancellationToken.None) // tslint:disable-line
const watchOptions = this.apiVersion.gte(API.v380)
? this.configuration.watchOptions
: undefined
const configureOptions: Proto.ConfigureRequestArguments = {
hostInfo: 'coc-nvim',
preferences: {
providePrefixAndSuffixTextForRename: true,
allowRenameOfImportPath: true,
},
watchOptions
}
this.executeWithoutWaitingForResponse('configure', configureOptions) // tslint:disable-line
this.setCompilerOptionsForInferredProjects(this._configuration)
if (resendModels) {
this._onResendModelsRequested.fire(void 0)
this.diagnosticsManager.reInitialize()
this.bufferSyncSupport.reinitialize()
}
// Reconfigure any plugins
for (const [config, pluginName] of this.pluginManager.configurations()) {
this.configurePlugin(config, pluginName)
}
}

View file

@ -64,6 +64,11 @@ export class TypeScriptServiceConfiguration {
return TsServerLogLevel.fromString(this._configuration.get<string | null>('log', null))
}
// public readonly watchOptions: protocol.WatchOptions | undefined;
public get watchOptions(): protocol.WatchOptions | undefined {
return this._configuration.get<protocol.WatchOptions>('watchOptions')
}
public get typingsCacheLocation(): string {
return this._configuration.get<string>('typingsCacheLocation', '')
}