rework function snippet
This commit is contained in:
parent
ec6e406594
commit
51893f971d
3 changed files with 112 additions and 48 deletions
src/server
|
@ -10,7 +10,7 @@ import * as PConst from '../protocol.const'
|
|||
import { ITypeScriptServiceClient } from '../typescriptService'
|
||||
import API from '../utils/api'
|
||||
import { applyCodeAction } from '../utils/codeAction'
|
||||
import { convertCompletionEntry } from '../utils/completionItem'
|
||||
import { convertCompletionEntry, getParameterListParts } from '../utils/completionItem'
|
||||
import * as Previewer from '../utils/previewer'
|
||||
import * as typeConverters from '../utils/typeConverters'
|
||||
import TypingsStatus from '../utils/typingsStatus'
|
||||
|
@ -337,52 +337,21 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP
|
|||
item: CompletionItem,
|
||||
detail: Proto.CompletionEntryDetails
|
||||
): void {
|
||||
let hasOptionalParameters = false
|
||||
let hasAddedParameters = false
|
||||
|
||||
let snippet = ''
|
||||
const methodName = detail.displayParts.find(
|
||||
part => part.kind === 'methodName'
|
||||
)
|
||||
snippet += item.insertText || (methodName && methodName.text) || item.label // tslint:disable-line
|
||||
snippet += '('
|
||||
let holderIndex = 1
|
||||
let parenCount = 0
|
||||
let i = 0
|
||||
for (; i < detail.displayParts.length; ++i) {
|
||||
const part = detail.displayParts[i]
|
||||
// Only take top level paren names
|
||||
if (part.kind === 'parameterName' && parenCount === 1) {
|
||||
const next = detail.displayParts[i + 1]
|
||||
// Skip optional parameters
|
||||
const nameIsFollowedByOptionalIndicator = next && next.text === '?'
|
||||
if (!nameIsFollowedByOptionalIndicator) {
|
||||
if (hasAddedParameters) snippet += ', '
|
||||
hasAddedParameters = true
|
||||
// tslint:disable-next-line:no-invalid-template-strings
|
||||
snippet += '${' + holderIndex + ':' + part.text + '}'
|
||||
holderIndex = holderIndex + 1
|
||||
}
|
||||
hasOptionalParameters =
|
||||
hasOptionalParameters || nameIsFollowedByOptionalIndicator
|
||||
} else if (part.kind === 'punctuation') {
|
||||
if (part.text === '(') {
|
||||
++parenCount
|
||||
} else if (part.text === ')') {
|
||||
--parenCount
|
||||
} else if (part.text === '...' && parenCount === 1) {
|
||||
// Found rest parmeter. Do not fill in any further arguments
|
||||
hasOptionalParameters = true
|
||||
break
|
||||
}
|
||||
let { displayParts } = detail
|
||||
let snippet = (item.insertText || item.label) + '(' // tslint:disable-line
|
||||
const parameterListParts = getParameterListParts(displayParts)
|
||||
let { parts, hasOptionalParameters } = parameterListParts
|
||||
let idx = 1
|
||||
for (let part of parts) {
|
||||
snippet += '${' + idx + ':' + part.text + '}' // tslint:disable-line
|
||||
if (idx == parts.length) {
|
||||
if (hasOptionalParameters) snippet += '${' + (idx + 1) + '}' // tslint:disable-line
|
||||
} else {
|
||||
snippet += ', '
|
||||
}
|
||||
idx = idx + 1
|
||||
}
|
||||
if (hasOptionalParameters) {
|
||||
// tslint:disable-next-line:no-invalid-template-strings
|
||||
snippet += '${' + holderIndex + '}'
|
||||
}
|
||||
snippet += ')'
|
||||
snippet += '$0'
|
||||
snippet += ')$0'
|
||||
// tslint:disable-next-line:deprecation
|
||||
item.insertText = snippet
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
export class Kind {
|
||||
public static readonly alias = 'alias'
|
||||
public static readonly callSignature = 'call'
|
||||
|
@ -12,7 +13,6 @@ export class Kind {
|
|||
public static readonly directory = 'directory'
|
||||
public static readonly enum = 'enum'
|
||||
public static readonly externalModuleName = 'external module name'
|
||||
public static readonly file = 'file'
|
||||
public static readonly function = 'function'
|
||||
public static readonly indexSignature = 'index'
|
||||
public static readonly interface = 'interface'
|
||||
|
@ -30,10 +30,43 @@ export class Kind {
|
|||
public static readonly type = 'type'
|
||||
public static readonly variable = 'var'
|
||||
public static readonly warning = 'warning'
|
||||
public static readonly string = 'string'
|
||||
public static readonly parameter = 'parameter'
|
||||
}
|
||||
|
||||
|
||||
export class DiagnosticCategory {
|
||||
public static readonly error = 'error'
|
||||
public static readonly warning = 'warning'
|
||||
public static readonly suggestion = 'suggestion'
|
||||
}
|
||||
|
||||
export class KindModifiers {
|
||||
public static readonly optional = 'optional'
|
||||
public static readonly color = 'color'
|
||||
|
||||
public static readonly dtsFile = '.d.ts'
|
||||
public static readonly tsFile = '.ts'
|
||||
public static readonly tsxFile = '.tsx'
|
||||
public static readonly jsFile = '.js'
|
||||
public static readonly jsxFile = '.jsx'
|
||||
public static readonly jsonFile = '.json'
|
||||
|
||||
public static readonly fileExtensionKindModifiers = [
|
||||
KindModifiers.dtsFile,
|
||||
KindModifiers.tsFile,
|
||||
KindModifiers.tsxFile,
|
||||
KindModifiers.jsFile,
|
||||
KindModifiers.jsxFile,
|
||||
KindModifiers.jsonFile,
|
||||
]
|
||||
}
|
||||
|
||||
export class DisplayPartKind {
|
||||
public static readonly functionName = 'functionName'
|
||||
public static readonly methodName = 'methodName'
|
||||
public static readonly parameterName = 'parameterName'
|
||||
public static readonly propertyName = 'propertyName'
|
||||
public static readonly punctuation = 'punctuation'
|
||||
public static readonly text = 'text'
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { workspace } from 'coc.nvim'
|
||||
import { CompletionItem, CompletionItemKind, InsertTextFormat, Position, TextEdit } from 'vscode-languageserver-protocol'
|
||||
import { CompletionItem, CompletionItemKind, InsertTextFormat, Position } from 'vscode-languageserver-protocol'
|
||||
import * as Proto from '../protocol'
|
||||
import * as PConst from '../protocol.const'
|
||||
|
||||
|
@ -13,6 +13,11 @@ interface CommitCharactersSettings {
|
|||
readonly useCodeSnippetsOnMethodSuggest: boolean
|
||||
}
|
||||
|
||||
interface ParamterListParts {
|
||||
readonly parts: ReadonlyArray<Proto.SymbolDisplayPart>
|
||||
readonly hasOptionalParameters: boolean
|
||||
}
|
||||
|
||||
export function convertCompletionEntry(
|
||||
tsEntry: Proto.CompletionEntry,
|
||||
uri: string,
|
||||
|
@ -97,7 +102,6 @@ function convertKind(kind: string): CompletionItemKind {
|
|||
case PConst.Kind.interface:
|
||||
return CompletionItemKind.Interface
|
||||
case PConst.Kind.warning:
|
||||
case PConst.Kind.file:
|
||||
case PConst.Kind.script:
|
||||
return CompletionItemKind.File
|
||||
case PConst.Kind.directory:
|
||||
|
@ -140,3 +144,61 @@ function getCommitCharacters(tsEntry: Proto.CompletionEntry, settings: CommitCha
|
|||
}
|
||||
return commitCharacters.length === 0 ? undefined : commitCharacters
|
||||
}
|
||||
|
||||
export function getParameterListParts(
|
||||
displayParts: ReadonlyArray<Proto.SymbolDisplayPart>
|
||||
): ParamterListParts {
|
||||
const parts: Proto.SymbolDisplayPart[] = []
|
||||
let isInMethod = false
|
||||
let hasOptionalParameters = false
|
||||
let parenCount = 0
|
||||
let braceCount = 0
|
||||
|
||||
outer: for (let i = 0; i < displayParts.length; ++i) {
|
||||
const part = displayParts[i]
|
||||
switch (part.kind) {
|
||||
case PConst.DisplayPartKind.methodName:
|
||||
case PConst.DisplayPartKind.functionName:
|
||||
case PConst.DisplayPartKind.text:
|
||||
case PConst.DisplayPartKind.propertyName:
|
||||
if (parenCount === 0 && braceCount === 0) {
|
||||
isInMethod = true
|
||||
}
|
||||
break
|
||||
|
||||
case PConst.DisplayPartKind.parameterName:
|
||||
if (parenCount === 1 && isInMethod) {
|
||||
// Only take top level paren names
|
||||
const next = displayParts[i + 1]
|
||||
// Skip optional parameters
|
||||
const nameIsFollowedByOptionalIndicator = next && next.text === '?'
|
||||
if (!nameIsFollowedByOptionalIndicator) {
|
||||
parts.push(part)
|
||||
}
|
||||
hasOptionalParameters = hasOptionalParameters || nameIsFollowedByOptionalIndicator
|
||||
}
|
||||
break
|
||||
|
||||
case PConst.DisplayPartKind.punctuation:
|
||||
if (part.text === '(') {
|
||||
++parenCount
|
||||
} else if (part.text === ')') {
|
||||
--parenCount
|
||||
if (parenCount <= 0 && isInMethod) {
|
||||
break outer
|
||||
}
|
||||
} else if (part.text === '...' && parenCount === 1) {
|
||||
// Found rest parmeter. Do not fill in any further arguments
|
||||
hasOptionalParameters = true
|
||||
break outer
|
||||
} else if (part.text === '{') {
|
||||
++braceCount
|
||||
} else if (part.text === '}') {
|
||||
--braceCount
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return { hasOptionalParameters, parts }
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue