|
| 1 | +import * as vscode from 'vscode' |
| 2 | +import { getActiveRegularEditor } from '@zardoy/vscode-utils' |
| 3 | +import { watchExtensionSettings } from '@zardoy/vscode-utils/build/settings' |
| 4 | +import { getExtensionSetting, Settings } from 'vscode-framework' |
| 5 | +import { oneOf } from '@zardoy/utils' |
| 6 | + |
| 7 | +export default (tsApi: { onCompletionAccepted }) => { |
| 8 | + let justAcceptedReturnKeywordSuggestion = false |
| 9 | + |
| 10 | + tsApi.onCompletionAccepted((item: vscode.CompletionItem & { document: vscode.TextDocument }) => { |
| 11 | + const enableMethodSnippets = vscode.workspace.getConfiguration(process.env.IDS_PREFIX, item.document).get('enableMethodSnippets') |
| 12 | + const { insertText, documentation = '', kind } = item |
| 13 | + if (kind === vscode.CompletionItemKind.Keyword && insertText === 'return ') { |
| 14 | + justAcceptedReturnKeywordSuggestion = true |
| 15 | + } |
| 16 | + |
| 17 | + const documentationString = documentation instanceof vscode.MarkdownString ? documentation.value : documentation |
| 18 | + const insertFuncArgs = /<!-- insert-func: (.*)-->/.exec(documentationString)?.[1] |
| 19 | + console.debug('insertFuncArgs', insertFuncArgs) |
| 20 | + if (enableMethodSnippets && insertFuncArgs !== undefined) { |
| 21 | + const editor = getActiveRegularEditor()! |
| 22 | + const startPos = editor.selection.start |
| 23 | + const nextSymbol = editor.document.getText(new vscode.Range(startPos, startPos.translate(0, 1))) |
| 24 | + if (!['(', '.'].includes(nextSymbol)) { |
| 25 | + const snippet = new vscode.SnippetString('') |
| 26 | + snippet.appendText('(') |
| 27 | + const args = insertFuncArgs.split(',') |
| 28 | + for (let [i, arg] of args.entries()) { |
| 29 | + if (!arg) continue |
| 30 | + // skip empty, but add tabstops if we explicitly want it! |
| 31 | + if (arg === ' ') arg = '' |
| 32 | + snippet.appendPlaceholder(arg) |
| 33 | + if (i !== args.length - 1) snippet.appendText(', ') |
| 34 | + } |
| 35 | + |
| 36 | + snippet.appendText(')') |
| 37 | + void editor.insertSnippet(snippet, undefined, { |
| 38 | + undoStopAfter: false, |
| 39 | + undoStopBefore: false, |
| 40 | + }) |
| 41 | + if (vscode.workspace.getConfiguration('editor.parameterHints').get('enabled')) { |
| 42 | + void vscode.commands.executeCommand('editor.action.triggerParameterHints') |
| 43 | + } |
| 44 | + } |
| 45 | + } |
| 46 | + }) |
| 47 | + |
| 48 | + conditionallyRegister( |
| 49 | + 'suggestions.keywordsInsertText', |
| 50 | + () => |
| 51 | + vscode.workspace.onDidChangeTextDocument(({ document, contentChanges, reason }) => { |
| 52 | + if (!justAcceptedReturnKeywordSuggestion) return |
| 53 | + if (document !== vscode.window.activeTextEditor?.document) return |
| 54 | + try { |
| 55 | + if (oneOf(reason, vscode.TextDocumentChangeReason.Redo, vscode.TextDocumentChangeReason.Undo)) { |
| 56 | + return |
| 57 | + } |
| 58 | + |
| 59 | + const char = contentChanges[0]?.text |
| 60 | + if (char?.length !== 1 || contentChanges.some(({ text }) => text !== char)) { |
| 61 | + return |
| 62 | + } |
| 63 | + |
| 64 | + if (char === ';') { |
| 65 | + void vscode.window.activeTextEditor.edit(builder => { |
| 66 | + for (const { range } of contentChanges) { |
| 67 | + const pos = range.start |
| 68 | + builder.delete(new vscode.Range(pos.translate(0, -1), pos)) |
| 69 | + } |
| 70 | + }) |
| 71 | + } |
| 72 | + } finally { |
| 73 | + justAcceptedReturnKeywordSuggestion = false |
| 74 | + } |
| 75 | + }), |
| 76 | + val => val !== 'none', |
| 77 | + ) |
| 78 | +} |
| 79 | + |
| 80 | +const conditionallyRegister = <T extends keyof Settings>( |
| 81 | + settingKey: T, |
| 82 | + registerFn: () => vscode.Disposable, |
| 83 | + acceptSettingValue: (val: Settings[T]) => boolean = val => !!val, |
| 84 | +) => { |
| 85 | + let disposable: vscode.Disposable | undefined |
| 86 | + const changeRegisterState = () => { |
| 87 | + const registerState = acceptSettingValue(getExtensionSetting(settingKey)) |
| 88 | + if (registerState) { |
| 89 | + if (!disposable) disposable = registerFn() |
| 90 | + } else { |
| 91 | + disposable?.dispose() |
| 92 | + disposable = undefined |
| 93 | + } |
| 94 | + } |
| 95 | + |
| 96 | + changeRegisterState() |
| 97 | + watchExtensionSettings([settingKey], changeRegisterState) |
| 98 | +} |
0 commit comments