From 35de441a9a3404a582eea44505336641c59a10d7 Mon Sep 17 00:00:00 2001 From: Vitaly Turovsky Date: Tue, 11 Jul 2023 22:37:33 +0300 Subject: [PATCH] fix: don't skip `this` when insert text for method completions is enabled fixes #148 test: add first tests for insert text mode! --- .../src/completions/functionCompletions.ts | 2 +- .../completions/objectLiteralCompletions.ts | 2 +- typescript/src/completionsAtPosition.ts | 1 - typescript/src/utils.ts | 3 +-- typescript/test/completions.spec.ts | 26 ++++++++++++++++++- typescript/test/shared.ts | 4 +++ typescript/test/testing.ts | 7 +++-- 7 files changed, 37 insertions(+), 8 deletions(-) diff --git a/typescript/src/completions/functionCompletions.ts b/typescript/src/completions/functionCompletions.ts index 7a5e13a6..7b13e1d5 100644 --- a/typescript/src/completions/functionCompletions.ts +++ b/typescript/src/completions/functionCompletions.ts @@ -44,7 +44,7 @@ export default (entries: ts.CompletionEntry[]) => { if (!methodSnippet || resolveData.isAmbiguous) return return { ...entry, - insertText: insertTextAfterEntry(entry, `(${methodSnippet.map((x, i) => `$\{${i + 1}:${x}}`).join(', ')})`), + insertText: insertTextAfterEntry(entry.insertText ?? entry.name, `(${methodSnippet.map((x, i) => `$\{${i + 1}:${x}}`).join(', ')})`), labelDetails: { detail: `(${methodSnippet.join(', ')})`, description: ts.displayPartsToString(entry.sourceDisplay), diff --git a/typescript/src/completions/objectLiteralCompletions.ts b/typescript/src/completions/objectLiteralCompletions.ts index 293665ff..0dbaef78 100644 --- a/typescript/src/completions/objectLiteralCompletions.ts +++ b/typescript/src/completions/objectLiteralCompletions.ts @@ -66,7 +66,7 @@ export default (prior: ts.CompletionInfo): ts.CompletionEntry[] | void => { const insertSnippetVariant = completingStyleMap.find(([, detector]) => detector(type!, typeChecker))?.[0] ?? fallbackSnippet if (!insertSnippetVariant) continue const [insertSnippetText, insertSnippetPreview] = typeof insertSnippetVariant === 'function' ? insertSnippetVariant() : insertSnippetVariant - let insertText = insertTextAfterEntry(entry, insertSnippetText) + let insertText = insertTextAfterEntry(entry.name, insertSnippetText) if (node.getSourceFile().getFullText()[position] === ',') insertText = insertText.slice(0, -1) const index = entries.indexOf(entry) entries.splice(index + (keepOriginal === 'before' ? 1 : 0), keepOriginal === 'remove' ? 1 : 0, { diff --git a/typescript/src/completionsAtPosition.ts b/typescript/src/completionsAtPosition.ts index 0f2a7b4c..8a8bd31d 100644 --- a/typescript/src/completionsAtPosition.ts +++ b/typescript/src/completionsAtPosition.ts @@ -2,7 +2,6 @@ import _ from 'lodash' import { compact } from '@zardoy/utils' import escapeStringRegexp from 'escape-string-regexp' import inKeywordCompletions from './completions/inKeywordCompletions' -// import * as emmet from '@vscode/emmet-helper' import isInBannedPosition from './completions/isInBannedPosition' import { GetConfig } from './types' import { findChildContainingExactPosition, findChildContainingPosition, isTs5, patchMethod } from './utils' diff --git a/typescript/src/utils.ts b/typescript/src/utils.ts index f3c6130a..ad0731d4 100644 --- a/typescript/src/utils.ts +++ b/typescript/src/utils.ts @@ -295,8 +295,7 @@ export const patchMethod = (obj: T, method: K, overriden: } } -export const insertTextAfterEntry = (entryOrName: ts.CompletionEntry | string, appendText: string) => - (typeof entryOrName === 'string' ? entryOrName : entryOrName.name).replace(/\$/g, '\\$') + appendText +export const insertTextAfterEntry = (entryOrName: string, appendText: string) => entryOrName.replace(/\$/g, '\\$') + appendText export const matchParents: MatchParentsType = (node, treeToCompare) => { let first = true diff --git a/typescript/test/completions.spec.ts b/typescript/test/completions.spec.ts index bd11f941..5a4370f8 100644 --- a/typescript/test/completions.spec.ts +++ b/typescript/test/completions.spec.ts @@ -5,7 +5,7 @@ import { isGoodPositionMethodCompletion } from '../src/completions/isGoodPositio import { findChildContainingExactPosition, isTs5 } from '../src/utils' import handleCommand from '../src/specialCommands/handle' import constructMethodSnippet from '../src/constructMethodSnippet' -import { defaultConfigFunc, entrypoint, settingsOverride, sharedLanguageService } from './shared' +import { currentTestingContext, defaultConfigFunc, entrypoint, settingsOverride, sharedLanguageService } from './shared' import { fileContentsSpecialPositions, fourslashLikeTester, getCompletionsAtPosition, overrideSettings } from './testing' const { languageService, languageServiceHost, updateProject, getCurrentFile } = sharedLanguageService @@ -124,6 +124,12 @@ const compareMethodSnippetAgainstMarker = (inputMarkers: number[], marker: numbe expect(Array.isArray(expected) ? methodSnippet : snippetToInsert, `At marker ${marker}`).toEqual(expected) } +const assertCompletionInsertText = (marker: number, entryName: string | undefined, insertTextExpected: string) => { + const { entries } = getCompletionsAtPosition(currentTestingContext.markers[marker]!)! + const entry = entryName === undefined ? entries[0] : entries.find(({ name }) => name === entryName) + expect(entry?.insertText).toEqual(insertTextExpected) +} + describe('Method snippets', () => { test('Misc', () => { const [, _, markers] = fileContentsSpecialPositions(/* ts */ ` @@ -286,6 +292,24 @@ describe('Method snippets', () => { compareMethodSnippetAgainstMarker(markers, 1, 'ambiguous') compareMethodSnippetAgainstMarker(markers, 2, 'ambiguous') }) + + test('methodSnippetsInsertText all', () => { + overrideSettings({ + methodSnippetsInsertText: 'all', + }) + fileContentsSpecialPositions(/* ts */ ` + const a = (a, b) => {} + a/*1*/ + + class A { + test() { + test/*2*/ + } + } + `) + assertCompletionInsertText(1, 'a', 'a(${1:a}, ${2:b})') + assertCompletionInsertText(2, 'test', 'this.test()') + }) }) test('Emmet completion', () => { diff --git a/typescript/test/shared.ts b/typescript/test/shared.ts index 59b57111..60c8adae 100644 --- a/typescript/test/shared.ts +++ b/typescript/test/shared.ts @@ -19,3 +19,7 @@ export const settingsOverride: Partial = { tupleHelpSignature: true, } export const defaultConfigFunc = await getDefaultConfigFunc(settingsOverride) + +export const currentTestingContext = { + markers: [] as number[], +} diff --git a/typescript/test/testing.ts b/typescript/test/testing.ts index 0aba35dc..280f2cae 100644 --- a/typescript/test/testing.ts +++ b/typescript/test/testing.ts @@ -1,7 +1,7 @@ import _ from 'lodash' import { getCompletionsAtPosition as getCompletionsAtPositionRaw } from '../src/completionsAtPosition' import { Configuration } from '../src/types' -import { defaultConfigFunc, entrypoint, sharedLanguageService, settingsOverride } from './shared' +import { defaultConfigFunc, entrypoint, sharedLanguageService, settingsOverride, currentTestingContext } from './shared' interface CompletionPartMatcher { names?: string[] @@ -29,7 +29,9 @@ export const getCompletionsAtPosition = (pos: number, { fileName = entrypoint, s const result = getCompletionsAtPositionRaw( fileName, pos, - {}, + { + includeCompletionsWithInsertText: true, + }, defaultConfigFunc, languageService, languageServiceHost.getScriptSnapshot(entrypoint)!, @@ -163,5 +165,6 @@ export const fileContentsSpecialPositions = (contents: string, fileName = entryp if (process.env.CI) throw new Error('Only positions not allowed on CI') return cursorPositionsOnly } + currentTestingContext.markers = cursorPositions[2] return cursorPositions }