fix snippet generate
This commit is contained in:
parent
0473880f30
commit
8febbe9418
3 changed files with 103 additions and 20 deletions
|
@ -15,6 +15,7 @@ import * as Previewer from '../utils/previewer'
|
|||
import * as typeConverters from '../utils/typeConverters'
|
||||
import TypingsStatus from '../utils/typingsStatus'
|
||||
import FileConfigurationManager, { SuggestOptions } from './fileConfigurationManager'
|
||||
import SnippetString from '../utils/SnippetString'
|
||||
|
||||
// command center
|
||||
export interface CommandItem {
|
||||
|
@ -352,26 +353,16 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP
|
|||
detail: Proto.CompletionEntryDetails
|
||||
): void {
|
||||
let { displayParts } = detail
|
||||
let snippet = (item.insertText || item.label) + '(' // tslint:disable-line
|
||||
const parameterListParts = getParameterListParts(displayParts)
|
||||
let { parts, hasOptionalParameters } = parameterListParts
|
||||
let idx = 1
|
||||
if (parts.length == 0 && hasOptionalParameters) {
|
||||
item.insertText = snippet + '${1})$0'
|
||||
return
|
||||
const snippet = new SnippetString()
|
||||
snippet.appendText(`${item.insertText || item.label}(`)
|
||||
appendJoinedPlaceholders(snippet, parameterListParts.parts, ', ')
|
||||
if (parameterListParts.hasOptionalParameters) {
|
||||
snippet.appendTabstop()
|
||||
}
|
||||
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
|
||||
}
|
||||
snippet += ')$0'
|
||||
// tslint:disable-next-line:deprecation
|
||||
item.insertText = snippet
|
||||
snippet.appendText(')')
|
||||
snippet.appendTabstop(0)
|
||||
item.insertText = snippet.value
|
||||
}
|
||||
|
||||
private async isValidFunctionCompletionContext(
|
||||
|
@ -415,3 +406,17 @@ function shouldExcludeCompletionEntry(
|
|||
|| (!completionConfiguration.autoImports && element.hasAction)
|
||||
)
|
||||
}
|
||||
|
||||
function appendJoinedPlaceholders(
|
||||
snippet: SnippetString,
|
||||
parts: ReadonlyArray<Proto.SymbolDisplayPart>,
|
||||
joiner: string
|
||||
) {
|
||||
for (let i = 0; i < parts.length; ++i) {
|
||||
const paramterPart = parts[i]
|
||||
snippet.appendPlaceholder(paramterPart.text)
|
||||
if (i !== parts.length - 1) {
|
||||
snippet.appendText(joiner)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
79
src/server/utils/SnippetString.ts
Normal file
79
src/server/utils/SnippetString.ts
Normal file
|
@ -0,0 +1,79 @@
|
|||
export default class SnippetString {
|
||||
|
||||
static isSnippetString(thing: any): thing is SnippetString {
|
||||
if (thing instanceof SnippetString) {
|
||||
return true
|
||||
}
|
||||
if (!thing) {
|
||||
return false
|
||||
}
|
||||
return typeof (<SnippetString>thing).value === 'string'
|
||||
}
|
||||
|
||||
private static _escape(value: string): string {
|
||||
return value.replace(/\$|}|\\/g, '\\$&')
|
||||
}
|
||||
|
||||
private _tabstop: number = 1
|
||||
|
||||
value: string
|
||||
|
||||
constructor(value?: string) {
|
||||
this.value = value || ''
|
||||
}
|
||||
|
||||
appendText(string: string): SnippetString {
|
||||
this.value += SnippetString._escape(string)
|
||||
return this
|
||||
}
|
||||
|
||||
appendTabstop(number: number = this._tabstop++): SnippetString {
|
||||
this.value += '$'
|
||||
this.value += number
|
||||
return this
|
||||
}
|
||||
|
||||
appendPlaceholder(value: string | ((snippet: SnippetString) => any), number: number = this._tabstop++): SnippetString {
|
||||
|
||||
if (typeof value === 'function') {
|
||||
const nested = new SnippetString()
|
||||
nested._tabstop = this._tabstop
|
||||
value(nested)
|
||||
this._tabstop = nested._tabstop
|
||||
value = nested.value
|
||||
} else {
|
||||
value = SnippetString._escape(value)
|
||||
}
|
||||
|
||||
this.value += '${'
|
||||
this.value += number
|
||||
this.value += ':'
|
||||
this.value += value
|
||||
this.value += '}'
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
appendVariable(name: string, defaultValue?: string | ((snippet: SnippetString) => any)): SnippetString {
|
||||
|
||||
if (typeof defaultValue === 'function') {
|
||||
const nested = new SnippetString()
|
||||
nested._tabstop = this._tabstop
|
||||
defaultValue(nested)
|
||||
this._tabstop = nested._tabstop
|
||||
defaultValue = nested.value
|
||||
|
||||
} else if (typeof defaultValue === 'string') {
|
||||
defaultValue = defaultValue.replace(/\$|}/g, '\\$&')
|
||||
}
|
||||
|
||||
this.value += '${'
|
||||
this.value += name
|
||||
if (defaultValue) {
|
||||
this.value += ':'
|
||||
this.value += defaultValue
|
||||
}
|
||||
this.value += '}'
|
||||
return this
|
||||
}
|
||||
}
|
|
@ -178,7 +178,7 @@ export function getParameterListParts(
|
|||
break
|
||||
|
||||
case PConst.DisplayPartKind.parameterName:
|
||||
if (parenCount === 1 && isInMethod) {
|
||||
if (parenCount === 1 && braceCount === 0 && isInMethod) {
|
||||
// Only take top level paren names
|
||||
const next = displayParts[i + 1]
|
||||
// Skip optional parameters
|
||||
|
@ -210,6 +210,5 @@ export function getParameterListParts(
|
|||
break
|
||||
}
|
||||
}
|
||||
|
||||
return { hasOptionalParameters, parts }
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue