From 5a1a41aba1d5b74407ec7f87eff8b410bfbaafaa Mon Sep 17 00:00:00 2001 From: Vitaly <vital2580@icloud.com> Date: Tue, 28 Nov 2023 03:51:26 +0300 Subject: [PATCH] feat: Speed up a bit JSX linked editing by simply caching previous response --- src/configurationType.ts | 6 ++++ typescript/src/decorateLinkedEditing.ts | 37 +++++++++++++++++++++++++ typescript/src/decorateProxy.ts | 2 ++ 3 files changed, 45 insertions(+) create mode 100644 typescript/src/decorateLinkedEditing.ts diff --git a/src/configurationType.ts b/src/configurationType.ts index b2ac606..73981b7 100644 --- a/src/configurationType.ts +++ b/src/configurationType.ts @@ -582,6 +582,12 @@ export type Configuration = { * @default false */ 'experiments.enableInsertNameOfSuggestionFix': boolean + /** + * Speed up JSX linked editing by not using actual tsserver command when possible, which in theory may introduce some inconsistencies. + * Note that currently it doesn't really help if you have `"typescript.tsserver.useSyntaxServer": "auto"` in the settings. + * @default true + */ + 'experiments.speedLinkedEditing': boolean /** * Map *symbol - array of modules* to change sorting of imports - first available takes precedence in auto import code fixes (+ import all action) * diff --git a/typescript/src/decorateLinkedEditing.ts b/typescript/src/decorateLinkedEditing.ts new file mode 100644 index 0000000..a21705d --- /dev/null +++ b/typescript/src/decorateLinkedEditing.ts @@ -0,0 +1,37 @@ +import { GetConfig } from './types' + +export default (proxy: ts.LanguageService, languageService: ts.LanguageService, languageServiceHost: ts.LanguageServiceHost, c: GetConfig) => { + // patch JSX tag linked editing to improve performance (needed for great user experience) + + let lastLinkedEditingRangeRequest: + | { + pos: number + fileName: string + result: ts.LinkedEditingInfo + } + | undefined + proxy.getLinkedEditingRangeAtPosition = (fileName, position) => { + if ( + c('experiments.speedLinkedEditing') && + lastLinkedEditingRangeRequest && + lastLinkedEditingRangeRequest.pos === position - 1 && + lastLinkedEditingRangeRequest.fileName === fileName + ) { + lastLinkedEditingRangeRequest.pos = position + lastLinkedEditingRangeRequest.result.ranges[0]!.length++ + lastLinkedEditingRangeRequest.result.ranges[1]!.start++ + lastLinkedEditingRangeRequest.result.ranges[1]!.length++ + return lastLinkedEditingRangeRequest.result + } + lastLinkedEditingRangeRequest = undefined + + const prior = languageService.getLinkedEditingRangeAtPosition(fileName, position) + if (!prior) return + lastLinkedEditingRangeRequest = { + pos: position, + fileName, + result: globalThis.structuredClone(prior), + } + return prior + } +} diff --git a/typescript/src/decorateProxy.ts b/typescript/src/decorateProxy.ts index 387c85c..6886ae7 100644 --- a/typescript/src/decorateProxy.ts +++ b/typescript/src/decorateProxy.ts @@ -19,6 +19,7 @@ import decorateSignatureHelp from './decorateSignatureHelp' import decorateFindRenameLocations from './decorateFindRenameLocations' import decorateQuickInfoAtPosition from './decorateQuickInfoAtPosition' import decorateEditsForFileRename from './decorateEditsForFileRename' +import decorateLinkedEditing from './decorateLinkedEditing' /** @internal */ export const thisPluginMarker = '__essentialPluginsMarker__' @@ -102,6 +103,7 @@ export const decorateLanguageService = ( decorateSignatureHelp(proxy, languageService, languageServiceHost, c) decorateFindRenameLocations(proxy, languageService, c) decorateQuickInfoAtPosition(proxy, languageService, languageServiceHost, c) + decorateLinkedEditing(proxy, languageService, languageServiceHost, c) libDomPatching(languageServiceHost, c)