diff --git a/package.json b/package.json index 3e664d9..ac16efe 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,11 @@ { "name": "coc-tsserver", - "version": "1.0.11", + "version": "1.1.0", "description": "tsserver extension for coc", "main": "lib/index.js", "publisher": "chemzqm", "engines": { - "coc": "^0.0.15" + "coc": "^0.0.24" }, "scripts": { "clean": "rimraf lib", @@ -167,31 +167,6 @@ "default": true, "description": "Enable codeLens for references" }, - "typescript.preferences.completion.useCodeSnippetsOnMethodSuggest": { - "type": "boolean", - "default": true, - "description": "Enable snippet for method suggestion" - }, - "typescript.preferences.completion.nameSuggestions": { - "type": "boolean", - "default": true, - "description": "Complete for warning type of tsserver" - }, - "typescript.preferences.completion.autoImportSuggestions": { - "type": "boolean", - "default": true, - "description": "Enable auto import suggestions for completion" - }, - "typescript.preferences.completion.commaAfterImport": { - "type": "boolean", - "default": true, - "description": "Add comma after import" - }, - "typescript.preferences.completion.moduleExports": { - "type": "boolean", - "default": true, - "description": "Include completion for module.exports" - }, "typescript.preferences.importModuleSpecifier": { "type": "string", "default": "non-relative", @@ -212,6 +187,30 @@ "double" ] }, + "typescript.suggest.enabled": { + "type": "boolean", + "default": true + }, + "typescript.suggest.paths": { + "type": "boolean", + "default": true, + "description": "Enable/disable suggest paths in import statement and require calls" + }, + "typescript.suggest.commaAfterImport": { + "type": "boolean", + "default": true, + "description": "Add comma after import statement." + }, + "typescript.suggest.autoImports": { + "type": "boolean", + "default": true, + "description": "Enable/disable auto import suggests." + }, + "typescript.suggest.completeFunctionCalls": { + "type": "boolean", + "default": true, + "description": "Enable snippet for method suggestion" + }, "typescript.format.insertSpaceAfterCommaDelimiter": { "type": "boolean", "default": true @@ -276,27 +275,6 @@ "type": "boolean", "default": true }, - "javascript.preferences.completion.useCodeSnippetsOnMethodSuggest": { - "type": "boolean", - "default": true - }, - "javascript.preferences.completion.nameSuggestions": { - "type": "boolean", - "default": true - }, - "javascript.preferences.completion.autoImportSuggestions": { - "type": "boolean", - "default": true - }, - "javascript.preferences.completion.commaAfterImport": { - "type": "boolean", - "default": true - }, - "javascript.preferences.completion.moduleExports": { - "type": "boolean", - "default": true, - "description": "Include completion for module.exports" - }, "javascript.preferences.importModuleSpecifier": { "type": "string", "default": "non-relative", @@ -317,6 +295,34 @@ "double" ] }, + "javascript.suggest.names": { + "type": "boolean", + "default": true + }, + "javascript.suggest.enabled": { + "type": "boolean", + "default": true + }, + "javascript.suggest.paths": { + "type": "boolean", + "default": true, + "description": "Enable/disable suggest paths in import statement and require calls" + }, + "javascript.suggest.commaAfterImport": { + "type": "boolean", + "default": true, + "description": "Add comma after import statement." + }, + "javascript.suggest.autoImports": { + "type": "boolean", + "default": true, + "description": "Enable/disable auto import suggests." + }, + "javascript.suggest.completeFunctionCalls": { + "type": "boolean", + "default": true, + "description": "Enable snippet for method suggestion" + }, "javascript.format.insertSpaceAfterCommaDelimiter": { "type": "boolean", "default": true diff --git a/src/server/features/completionItemProvider.ts b/src/server/features/completionItemProvider.ts index 5acd8b3..4ca8cd6 100644 --- a/src/server/features/completionItemProvider.ts +++ b/src/server/features/completionItemProvider.ts @@ -14,7 +14,7 @@ import { convertCompletionEntry, resolveItem } from '../utils/completionItem' import * as Previewer from '../utils/previewer' import * as typeConverters from '../utils/typeConverters' import TypingsStatus from '../utils/typingsStatus' -import FileConfigurationManager, { CompletionOptions } from './fileConfigurationManager' +import FileConfigurationManager, { SuggestOptions } from './fileConfigurationManager' // command center export interface CommandItem { @@ -50,7 +50,7 @@ class ApplyCompletionCodeActionCommand implements CommandItem { export default class TypeScriptCompletionItemProvider implements CompletionItemProvider { public static readonly triggerCharacters = ['.', '@', '<'] - private completeOption: CompletionOptions + private completeOption: SuggestOptions constructor( private readonly client: ITypeScriptServiceClient, @@ -104,9 +104,9 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP const args: Proto.CompletionsRequestArgs = { ...typeConverters.Position.toFileLocationRequestArgs(file, position), - includeExternalModuleExports: completeOption.autoImportSuggestions, + includeExternalModuleExports: completeOption.autoImports, includeInsertTextCompletions: true, - triggerCharacter: triggerCharacter && triggerCharacter === '.' ? triggerCharacter : undefined + triggerCharacter: this.getTsTriggerCharacter(context) } let msg: Proto.CompletionEntry[] | undefined @@ -122,21 +122,14 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP const completionItems: CompletionItem[] = [] for (const element of msg) { - let { kind } = element - if (kind === PConst.Kind.warning - || kind === PConst.Kind.script) { - if (!completeOption.nameSuggestions || triggerCharacter == '.') { - continue - } - } - if (!completeOption.autoImportSuggestions && element.hasAction) { + if (!shouldExcludeCompletionEntry(element, completeOption)) { continue } const item = convertCompletionEntry( element, uri, position, - completeOption.useCodeSnippetsOnMethodSuggest, + completeOption.completeFunctionCalls, ) completionItems.push(item) } @@ -144,6 +137,17 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP return completionItems } + 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 + } + /** * Resolve complete item, could have documentation added * @@ -347,6 +351,7 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP if (!nameIsFollowedByOptionalIndicator) { if (hasAddedParameters) snippet += ', ' hasAddedParameters = true + // tslint:disable-next-line:no-invalid-template-strings snippet += '${' + holderIndex + ':' + part.text + '}' holderIndex = holderIndex + 1 } @@ -365,6 +370,7 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP } } if (hasOptionalParameters) { + // tslint:disable-next-line:no-invalid-template-strings snippet += '${' + holderIndex + '}' } snippet += ')' @@ -373,3 +379,15 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP item.textEdit = textEdit } } + +function shouldExcludeCompletionEntry( + element: Proto.CompletionEntry, + completionConfiguration: SuggestOptions +): boolean { + return ( + (!completionConfiguration.names && element.kind === PConst.Kind.warning) + || (!completionConfiguration.paths && + (element.kind === PConst.Kind.directory || element.kind === PConst.Kind.script || element.kind === PConst.Kind.externalModuleName)) + || (!completionConfiguration.autoImports && element.hasAction) + ) +} diff --git a/src/server/features/fileConfigurationManager.ts b/src/server/features/fileConfigurationManager.ts index dce4a4d..ab59fb9 100644 --- a/src/server/features/fileConfigurationManager.ts +++ b/src/server/features/fileConfigurationManager.ts @@ -30,11 +30,13 @@ interface FileConfiguration { preferences: Proto.UserPreferences } -export interface CompletionOptions { +export interface SuggestOptions { + readonly enabled: boolean + readonly names: boolean + readonly paths: boolean readonly commaAfterImport: boolean - readonly useCodeSnippetsOnMethodSuggest: boolean - readonly nameSuggestions: boolean - readonly autoImportSuggestions: boolean + readonly completeFunctionCalls: boolean + readonly autoImports: boolean } export default class FileConfigurationManager { @@ -120,14 +122,16 @@ export default class FileConfigurationManager { } } - public getCompleteOptions(languageId: string): CompletionOptions { + public getCompleteOptions(languageId: string): SuggestOptions { const lang = this.isTypeScriptDocument(languageId) ? 'typescript' : 'javascript' - const config = workspace.getConfiguration(`${lang}.preferences.completion`) + const config = workspace.getConfiguration(`${lang}.suggest`) return { - useCodeSnippetsOnMethodSuggest: config.get('useCodeSnippetsOnMethodSuggest', true), + enabled: config.get('enabled', true), + names: config.get('names', true), + paths: config.get('paths', true), commaAfterImport: config.get('commaAfterImport', true), - nameSuggestions: config.get('nameSuggestions', true), - autoImportSuggestions: config.get('autoImportSuggestions', true) + completeFunctionCalls: config.get('completeFunctionCalls', true), + autoImports: config.get('autoImports', true) } } @@ -135,23 +139,20 @@ export default class FileConfigurationManager { if (!this.client.apiVersion.gte(API.v290)) { return {} } - const config = workspace.getConfiguration(`${language}.preferences`) + const config = workspace.getConfiguration(`${language}`) return { + disableSuggestions: !config.get('suggest.enabled', true), importModuleSpecifierPreference: getImportModuleSpecifier(config) as any, - disableSuggestions: !config.get('suggestionActions.enabled', true), - quotePreference: getQuoteType(config), - includeCompletionsForModuleExports: config.get('completion.moduleExports', true), - includeCompletionsWithInsertText: true, - allowTextChangesInNewFiles: false, + quotePreference: config.get<'single' | 'double'>('preferences.quoteStyle', 'single'), + allowTextChangesInNewFiles: true, } } } type ModuleImportType = 'relative' | 'non-relative' | 'auto' -type QuoteType = 'single' | 'double' function getImportModuleSpecifier(config): ModuleImportType { - let val = config.get('importModuleSpecifier') + let val = config.get('preferences.importModuleSpecifier') switch (val) { case 'relative': return 'relative' @@ -161,15 +162,3 @@ function getImportModuleSpecifier(config): ModuleImportType { return 'auto' } } - -function getQuoteType(config): QuoteType { - let val = config.get('quoteStyle') - switch (val) { - case 'single': - return 'single' - case 'double': - return 'double' - default: - return 'single' - } -} diff --git a/src/server/schema.json b/src/server/schema.json deleted file mode 100644 index fb28acd..0000000 --- a/src/server/schema.json +++ /dev/null @@ -1,298 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema", - "properties": { - "tsserver.enable": { - "type": "boolean", - "default": true, - "description": "Enable tsserver extension" - }, - "tsserver.locale": { - "type": "string", - "default": "", - "description": "Locale of tsserver" - }, - "tsserver.typingsCacheLocation": { - "type": "string", - "default": "", - "description": "Folder path for cache typings" - }, - "tsserver.formatOnSave": { - "type": "boolean", - "default": false, - "description": "Format document on buffer will save" - }, - "tsserver.orgnizeImportOnSave": { - "type": "boolean", - "default": false, - "description": "Orgnize import on buffer will save" - }, - "tsserver.formatOnType": { - "type": "boolean", - "default": true, - "description": "Run format on type special characters." - }, - "tsserver.enableJavascript": { - "type": "boolean", - "default": true, - "description": "Use tsserver for javascript files" - }, - "tsserver.tsdk": { - "type": "string", - "default": "", - "description": "Directory contains tsserver.js, works for workspace only" - }, - "tsserver.npm": { - "type": "string", - "default": "", - "description": "Executable path of npm for download typings" - }, - "tsserver.log": { - "type": "string", - "default": "off", - "enum": ["normal", "terse", "verbose", "off"], - "description": "Log level of tsserver" - }, - "tsserver.trace.server": { - "type": "string", - "default": "off", - "enum": ["off", "messages", "verbose"], - "description": "Trace level of tsserver" - }, - "tserver.pluginNames": { - "type": "array", - "default": [], - "items": { - "type": "string" - }, - "description": "Module names of tsserver plugins" - }, - "tsserver.pluginRoot": { - "type": "string", - "default": "", - "description": "Folder contains tsserver plugins" - }, - "tsserver.debugPort": { - "type": "number", - "description": "Debug port number of tsserver" - }, - "tsserver.reportStyleChecksAsWarnings": { - "type": "boolean", - "default": true - }, - "tsserver.implicitProjectConfig.checkJs": { - "type": "boolean", - "default": false, - "description": "Enable checkJs for implicit project" - }, - "tsserver.implicitProjectConfig.experimentalDecorators": { - "type": "boolean", - "default": false, - "description": "Enable experimentalDecorators for implicit project" - }, - "tsserver.disableAutomaticTypeAcquisition": { - "type": "boolean", - "default": false, - "description": "Disable download of typings" - }, - "typescript.updateImportsOnFileMove.enable": { - "type": "boolean", - "default": true, - "description": "Enable update imports on file move." - }, - "typescript.implementationsCodeLens.enable": { - "type": "boolean", - "default": true, - "description": "Enable codeLens for implementations" - }, - "typescript.referencesCodeLens.enable": { - "type": "boolean", - "default": true, - "description": "Enable codeLens for references" - }, - "typescript.preferences.completion.useCodeSnippetsOnMethodSuggest": { - "type": "boolean", - "default": true, - "description": "Enable snippet for method suggestion" - }, - "typescript.preferences.completion.nameSuggestions": { - "type": "boolean", - "default": true, - "description": "Complete for warning type of tsserver" - }, - "typescript.preferences.completion.autoImportSuggestions": { - "type": "boolean", - "default": true, - "description": "Enable auto import suggestions for completion" - }, - "typescript.preferences.completion.commaAfterImport": { - "type": "boolean", - "default": true, - "description": "Add comma after import" - }, - "typescript.preferences.completion.moduleExports": { - "type": "boolean", - "default": true, - "description": "Include completion for module.exports" - }, - "typescript.preferences.importModuleSpecifier": { - "type": "string", - "default": "non-relative", - "enum": ["non-relative", "relative"] - }, - "typescript.preferences.suggestionActions.enabled": { - "type": "boolean", - "default": true - }, - "typescript.preferences.quoteStyle": { - "type": "string", - "default": "single", - "enum": ["single", "double"] - }, - "typescript.format.insertSpaceAfterCommaDelimiter": { - "type": "boolean", - "default": true - }, - "typescript.format.insertSpaceAfterConstructor": { - "type": "boolean", - "default": false - }, - "typescript.format.insertSpaceAfterSemicolonInForStatements": { - "type": "boolean", - "default": true - }, - "typescript.format.insertSpaceBeforeAndAfterBinaryOperators": { - "type": "boolean", - "default": true - }, - "typescript.format.insertSpaceAfterKeywordsInControlFlowStatements": { - "type": "boolean", - "default": true - }, - "typescript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": { - "type": "boolean", - "default": true - }, - "typescript.format.insertSpaceBeforeFunctionParenthesis": { - "type": "boolean", - "default": false - }, - "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": { - "type": "boolean", - "default": false - }, - "typescript.format.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": { - "type": "boolean", - "default": false - }, - "typescript.format.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": { - "type": "boolean", - "default": false - }, - "typescript.format.insertSpaceAfterTypeAssertion": { - "type": "boolean", - "default": false - }, - "typescript.format.placeOpenBraceOnNewLineForFunctions": { - "type": "boolean", - "default": false - }, - "typescript.format.placeOpenBraceOnNewLineForControlBlocks": { - "type": "boolean", - "default": false - }, - "javascript.updateImportsOnFileMove.enable": { - "type": "boolean", - "default": true - }, - "javascript.implementationsCodeLens.enable": { - "type": "boolean", - "default": true - }, - "javascript.referencesCodeLens.enable": { - "type": "boolean", - "default": true - }, - "javascript.preferences.completion.useCodeSnippetsOnMethodSuggest": { - "type": "boolean", - "default": true - }, - "javascript.preferences.completion.nameSuggestions": { - "type": "boolean", - "default": true - }, - "javascript.preferences.completion.autoImportSuggestions": { - "type": "boolean", - "default": true - }, - "javascript.preferences.importModuleSpecifier": { - "type": "string", - "default": "non-relative", - "enum": ["non-relative", "relative"] - }, - "javascript.preferences.suggestionActions.enabled": { - "type": "boolean", - "default": true - }, - "javascript.preferences.completion.commaAfterImport": { - "type": "boolean", - "default": true - }, - "javascript.preferences.quoteStyle": { - "type": "string", - "default": "single", - "enum": ["single", "double"] - }, - "javascript.format.insertSpaceAfterCommaDelimiter": { - "type": "boolean", - "default": true - }, - "javascript.format.insertSpaceAfterConstructor": { - "type": "boolean", - "default": false - }, - "javascript.format.insertSpaceAfterSemicolonInForStatements": { - "type": "boolean", - "default": true - }, - "javascript.format.insertSpaceBeforeAndAfterBinaryOperators": { - "type": "boolean", - "default": true - }, - "javascript.format.insertSpaceAfterKeywordsInControlFlowStatements": { - "type": "boolean", - "default": true - }, - "javascript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": { - "type": "boolean", - "default": true - }, - "javascript.format.insertSpaceBeforeFunctionParenthesis": { - "type": "boolean", - "default": false - }, - "javascript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": { - "type": "boolean", - "default": false - }, - "javascript.format.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": { - "type": "boolean", - "default": false - }, - "javascript.format.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": { - "type": "boolean", - "default": false - }, - "javascript.format.insertSpaceAfterTypeAssertion": { - "type": "boolean", - "default": false - }, - "javascript.format.placeOpenBraceOnNewLineForFunctions": { - "type": "boolean", - "default": false - }, - "javascript.format.placeOpenBraceOnNewLineForControlBlocks": { - "type": "boolean", - "default": false - } - } -} diff --git a/src/server/utils/api.ts b/src/server/utils/api.ts index 31dd07a..082c391 100644 --- a/src/server/utils/api.ts +++ b/src/server/utils/api.ts @@ -52,4 +52,8 @@ export default class API { public gte(other: API): boolean { return semver.gte(this.version, other.version) } + + public lt(other: API): boolean { + return !this.gte(other) + } }