Skip to content

Commit

Permalink
refactor(typescript): syntax only service context isolation
Browse files Browse the repository at this point in the history
  • Loading branch information
johnsoncodehk committed Apr 25, 2024
1 parent e05c357 commit 169ffb4
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 66 deletions.
48 changes: 33 additions & 15 deletions packages/typescript/lib/plugins/syntactic.ts
Expand Up @@ -12,7 +12,39 @@ import {
convertOutliningSpan,
convertTextChange
} from '../utils/lspConverters';
import { getLanguageService } from '../syntacticLanguageService';
import { createSyntaxOnlyService } from '../syntaxOnlyService';
import type * as ts from 'typescript';

const snapshots = new WeakMap<TextDocument, [number, ts.IScriptSnapshot]>();

let created: ReturnType<typeof createSyntaxOnlyService> | undefined;

export function getLanguageServiceByDocument(ts: typeof import('typescript'), document: TextDocument) {
if (!created) {
created = createSyntaxOnlyService(ts, true);
}
let cache = snapshots.get(document);
if (!cache || cache[0] !== document.version) {
const snapshot = ts.ScriptSnapshot.fromString(document.getText());
cache = [document.version, snapshot];
snapshots.set(document, cache);
created.updateFile(
document.uri,
cache[1],
document.languageId === 'javascript'
? ts.ScriptKind.JS
: document.languageId === 'javascriptreact'
? ts.ScriptKind.JSX
: document.languageId === 'typescriptreact'
? ts.ScriptKind.TSX
: ts.ScriptKind.TS
);
}
return {
languageService: created.languageService,
fileName: document.uri,
};
}

export function create(
ts: typeof import('typescript'),
Expand Down Expand Up @@ -141,17 +173,3 @@ export function create(
},
};
}

import type * as ts from 'typescript';

const snapshots = new WeakMap<TextDocument, [number, ts.IScriptSnapshot]>();

export function getLanguageServiceByDocument(ts: typeof import('typescript'), document: TextDocument) {
let cache = snapshots.get(document);
if (!cache || cache[0] !== document.version) {
const snapshot = ts.ScriptSnapshot.fromString(document.getText());
cache = [document.version, snapshot];
snapshots.set(document, cache);
}
return getLanguageService(ts, cache[1], document.languageId, true);
}
51 changes: 0 additions & 51 deletions packages/typescript/lib/syntacticLanguageService.ts

This file was deleted.

49 changes: 49 additions & 0 deletions packages/typescript/lib/syntaxOnlyService.ts
@@ -0,0 +1,49 @@
import type * as ts from 'typescript';

export function createSyntaxOnlyService(ts: typeof import('typescript'), syntaxOnly: boolean) {
let currentProjectVersion = -1;
let fileNames: string[] = [];

const scriptInfos = new Map<string, {
snapshot: ts.IScriptSnapshot;
kind: ts.ScriptKind;
version: number;
}>();
const host: ts.LanguageServiceHost = {
getProjectVersion: () => currentProjectVersion.toString(),
getScriptFileNames: () => fileNames,
getScriptVersion: () => currentProjectVersion.toString(),
getScriptSnapshot: fileName => scriptInfos.get(fileName)!.snapshot,
getScriptKind: fileName => scriptInfos.get(fileName)!.kind,
getCompilationSettings: () => ({}),
getCurrentDirectory: () => '',
getDefaultLibFileName: () => '',
readFile: () => undefined,
fileExists: fileName => scriptInfos.has(fileName),
};

return {
languageService: syntaxOnly
? ts.createLanguageService(host, undefined, ts.LanguageServiceMode.Syntactic)
: ts.createLanguageService(host),
updateFile,
};

function updateFile(fileName: string, snapshot: ts.IScriptSnapshot, scriptKind: ts.ScriptKind) {
let scriptInfo = scriptInfos.get(fileName);
if (scriptInfo?.snapshot === snapshot && scriptInfo.kind === scriptKind) {
return;
}
currentProjectVersion++;
scriptInfo = {
snapshot,
kind: scriptKind,
version: (scriptInfo?.version ?? 0) + 1,
};
const filesChanged = !scriptInfos.has(fileName);
scriptInfos.set(fileName, scriptInfo);
if (filesChanged) {
fileNames = [...scriptInfos.keys()];
}
}
}

0 comments on commit 169ffb4

Please sign in to comment.