Skip to content

Commit 107ee06

Browse files
committed
feat: customizeEnabledFeatures to allow disable some TS language service features per file or globally (e.g. completions or diagnostics)
feat: print warning in logs if some operation tooks too much time
1 parent c152df7 commit 107ee06

File tree

3 files changed

+60
-1
lines changed

3 files changed

+60
-1
lines changed

buildTsPlugin.mjs

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ const result = await buildTsPlugin('typescript', undefined, undefined, {
3030
js: 'let ts, tsFull;',
3131
// js: 'const log = (...args) => console.log(...args.map(a => JSON.stringify(a)))',
3232
},
33+
external: ['perf_hooks'],
3334
plugins: [
3435
{
3536
name: 'watch-notifier',

src/configurationType.ts

+16-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ScriptElementKind, ScriptKind } from 'typescript/lib/tsserverlibrary'
1+
import { ScriptElementKind, ScriptKind, LanguageService } from 'typescript/lib/tsserverlibrary'
22

33
type ReplaceRule = {
44
/**
@@ -660,6 +660,21 @@ export type Configuration = {
660660
typeAlias: string
661661
interface: string
662662
}
663+
customizeEnabledFeatures: {
664+
[path: string]:
665+
| 'disable-auto-invoked'
666+
// | 'disable-heavy-features'
667+
| {
668+
/** @default true */
669+
[feature in keyof LanguageService]: boolean
670+
}
671+
}
672+
// bigFilesLimitFeatures: 'do-not-limit' | 'limit-auto-invoking' | 'force-limit-all-features'
673+
/**
674+
* in kb default is 1.5mb
675+
* @default 100000
676+
*/
677+
// bigFilesThreshold: number
663678
/** @default false */
664679
enableHooksFile: boolean
665680
}

typescript/src/decorateProxy.ts

+43
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,49 @@ export const decorateLanguageService = (
139139
}
140140
}
141141

142+
const readonlyModeDisableFeatures: Array<keyof ts.LanguageService> = [
143+
'getOutliningSpans',
144+
'getSyntacticDiagnostics',
145+
'getSemanticDiagnostics',
146+
'getSuggestionDiagnostics',
147+
'provideInlayHints',
148+
'getLinkedEditingRangeAtPosition',
149+
'getApplicableRefactors',
150+
'getCompletionsAtPosition',
151+
'getDefinitionAndBoundSpan',
152+
'getFormattingEditsAfterKeystroke',
153+
'getDocumentHighlights',
154+
]
155+
for (const feature of readonlyModeDisableFeatures) {
156+
const orig = proxy[feature]
157+
proxy[feature] = (...args) => {
158+
const enabledFeaturesSetting = c('customizeEnabledFeatures') ?? {}
159+
const toDisableRaw =
160+
Object.entries(enabledFeaturesSetting).find(([path]) => {
161+
if (typeof args[0] !== 'string') return false
162+
return args[0].includes(path)
163+
})?.[1] ??
164+
enabledFeaturesSetting['*'] ??
165+
{}
166+
const toDisable: string[] =
167+
toDisableRaw === 'disable-auto-invoked'
168+
? // todo
169+
readonlyModeDisableFeatures
170+
: Object.entries(toDisableRaw)
171+
.filter(([, v]) => v === false)
172+
.map(([k]) => k)
173+
if (toDisable.includes(feature)) return undefined
174+
// eslint-disable-next-line @typescript-eslint/no-require-imports
175+
const performance = globalThis.performance ?? require('perf_hooks').performance
176+
const start = performance.now()
177+
//@ts-expect-error
178+
const result = orig(...args)
179+
const time = performance.now() - start
180+
if (time > 100) console.log(`[typescript-vscode-plugin perf warning] ${feature} took ${time}ms: ${args[0]} ${args[1]}`)
181+
return result
182+
}
183+
}
184+
142185
languageService[thisPluginMarker] = true
143186

144187
if (!__WEB__ && c('enableHooksFile')) {

0 commit comments

Comments
 (0)